xref: /openbsd/lib/libskey/put.c (revision 80c62621)
1 /* OpenBSD S/Key (put.c)
2  *
3  * Authors:
4  *          Neil M. Haller <nmh@thumper.bellcore.com>
5  *          Philip R. Karn <karn@chicago.qualcomm.com>
6  *          John S. Walden <jsw@thumper.bellcore.com>
7  *          Scott Chasin <chasin@crimelab.com>
8  *
9  * Dictionary lookup and extraction.
10  *
11  * $OpenBSD: put.c,v 1.14 2013/11/29 19:00:51 deraadt Exp $
12  */
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <assert.h>
18 #include <ctype.h>
19 
20 #include "skey.h"
21 
22 static unsigned int extract(char *, int, int);
23 static void standard(char *);
24 static void insert(char *, int, int, int);
25 static int wsrch(char *, int, int);
26 
27 /* Standard dictionary for integer-word translations */
28 static const char * const Wp[2048] = {
29 	"A",      "ABE",    "ACE",    "ACT",    "AD",     "ADA",    "ADD",
30 	"AGO",    "AID",    "AIM",    "AIR",    "ALL",    "ALP",    "AM",
31 	"AMY",    "AN",     "ANA",    "AND",    "ANN",    "ANT",    "ANY",
32 	"APE",    "APS",    "APT",    "ARC",    "ARE",    "ARK",    "ARM",
33 	"ART",    "AS",     "ASH",    "ASK",    "AT",     "ATE",    "AUG",
34 	"AUK",    "AVE",    "AWE",    "AWK",    "AWL",    "AWN",    "AX",
35 	"AYE",    "BAD",    "BAG",    "BAH",    "BAM",    "BAN",    "BAR",
36 	"BAT",    "BAY",    "BE",     "BED",    "BEE",    "BEG",    "BEN",
37 	"BET",    "BEY",    "BIB",    "BID",    "BIG",    "BIN",    "BIT",
38 	"BOB",    "BOG",    "BON",    "BOO",    "BOP",    "BOW",    "BOY",
39 	"BUB",    "BUD",    "BUG",    "BUM",    "BUN",    "BUS",    "BUT",
40 	"BUY",    "BY",     "BYE",    "CAB",    "CAL",    "CAM",    "CAN",
41 	"CAP",    "CAR",    "CAT",    "CAW",    "COD",    "COG",    "COL",
42 	"CON",    "COO",    "COP",    "COT",    "COW",    "COY",    "CRY",
43 	"CUB",    "CUE",    "CUP",    "CUR",    "CUT",    "DAB",    "DAD",
44 	"DAM",    "DAN",    "DAR",    "DAY",    "DEE",    "DEL",    "DEN",
45 	"DES",    "DEW",    "DID",    "DIE",    "DIG",    "DIN",    "DIP",
46 	"DO",     "DOE",    "DOG",    "DON",    "DOT",    "DOW",    "DRY",
47 	"DUB",    "DUD",    "DUE",    "DUG",    "DUN",    "EAR",    "EAT",
48 	"ED",     "EEL",    "EGG",    "EGO",    "ELI",    "ELK",    "ELM",
49 	"ELY",    "EM",     "END",    "EST",    "ETC",    "EVA",    "EVE",
50 	"EWE",    "EYE",    "FAD",    "FAN",    "FAR",    "FAT",    "FAY",
51 	"FED",    "FEE",    "FEW",    "FIB",    "FIG",    "FIN",    "FIR",
52 	"FIT",    "FLO",    "FLY",    "FOE",    "FOG",    "FOR",    "FRY",
53 	"FUM",    "FUN",    "FUR",    "GAB",    "GAD",    "GAG",    "GAL",
54 	"GAM",    "GAP",    "GAS",    "GAY",    "GEE",    "GEL",    "GEM",
55 	"GET",    "GIG",    "GIL",    "GIN",    "GO",     "GOT",    "GUM",
56 	"GUN",    "GUS",    "GUT",    "GUY",    "GYM",    "GYP",    "HA",
57 	"HAD",    "HAL",    "HAM",    "HAN",    "HAP",    "HAS",    "HAT",
58 	"HAW",    "HAY",    "HE",     "HEM",    "HEN",    "HER",    "HEW",
59 	"HEY",    "HI",     "HID",    "HIM",    "HIP",    "HIS",    "HIT",
60 	"HO",     "HOB",    "HOC",    "HOE",    "HOG",    "HOP",    "HOT",
61 	"HOW",    "HUB",    "HUE",    "HUG",    "HUH",    "HUM",    "HUT",
62 	"I",      "ICY",    "IDA",    "IF",     "IKE",    "ILL",    "INK",
63 	"INN",    "IO",     "ION",    "IQ",     "IRA",    "IRE",    "IRK",
64 	"IS",     "IT",     "ITS",    "IVY",    "JAB",    "JAG",    "JAM",
65 	"JAN",    "JAR",    "JAW",    "JAY",    "JET",    "JIG",    "JIM",
66 	"JO",     "JOB",    "JOE",    "JOG",    "JOT",    "JOY",    "JUG",
67 	"JUT",    "KAY",    "KEG",    "KEN",    "KEY",    "KID",    "KIM",
68 	"KIN",    "KIT",    "LA",     "LAB",    "LAC",    "LAD",    "LAG",
69 	"LAM",    "LAP",    "LAW",    "LAY",    "LEA",    "LED",    "LEE",
70 	"LEG",    "LEN",    "LEO",    "LET",    "LEW",    "LID",    "LIE",
71 	"LIN",    "LIP",    "LIT",    "LO",     "LOB",    "LOG",    "LOP",
72 	"LOS",    "LOT",    "LOU",    "LOW",    "LOY",    "LUG",    "LYE",
73 	"MA",     "MAC",    "MAD",    "MAE",    "MAN",    "MAO",    "MAP",
74 	"MAT",    "MAW",    "MAY",    "ME",     "MEG",    "MEL",    "MEN",
75 	"MET",    "MEW",    "MID",    "MIN",    "MIT",    "MOB",    "MOD",
76 	"MOE",    "MOO",    "MOP",    "MOS",    "MOT",    "MOW",    "MUD",
77 	"MUG",    "MUM",    "MY",     "NAB",    "NAG",    "NAN",    "NAP",
78 	"NAT",    "NAY",    "NE",     "NED",    "NEE",    "NET",    "NEW",
79 	"NIB",    "NIL",    "NIP",    "NIT",    "NO",     "NOB",    "NOD",
80 	"NON",    "NOR",    "NOT",    "NOV",    "NOW",    "NU",     "NUN",
81 	"NUT",    "O",      "OAF",    "OAK",    "OAR",    "OAT",    "ODD",
82 	"ODE",    "OF",     "OFF",    "OFT",    "OH",     "OIL",    "OK",
83 	"OLD",    "ON",     "ONE",    "OR",     "ORB",    "ORE",    "ORR",
84 	"OS",     "OTT",    "OUR",    "OUT",    "OVA",    "OW",     "OWE",
85 	"OWL",    "OWN",    "OX",     "PA",     "PAD",    "PAL",    "PAM",
86 	"PAN",    "PAP",    "PAR",    "PAT",    "PAW",    "PAY",    "PEA",
87 	"PEG",    "PEN",    "PEP",    "PER",    "PET",    "PEW",    "PHI",
88 	"PI",     "PIE",    "PIN",    "PIT",    "PLY",    "PO",     "POD",
89 	"POE",    "POP",    "POT",    "POW",    "PRO",    "PRY",    "PUB",
90 	"PUG",    "PUN",    "PUP",    "PUT",    "QUO",    "RAG",    "RAM",
91 	"RAN",    "RAP",    "RAT",    "RAW",    "RAY",    "REB",    "RED",
92 	"REP",    "RET",    "RIB",    "RID",    "RIG",    "RIM",    "RIO",
93 	"RIP",    "ROB",    "ROD",    "ROE",    "RON",    "ROT",    "ROW",
94 	"ROY",    "RUB",    "RUE",    "RUG",    "RUM",    "RUN",    "RYE",
95 	"SAC",    "SAD",    "SAG",    "SAL",    "SAM",    "SAN",    "SAP",
96 	"SAT",    "SAW",    "SAY",    "SEA",    "SEC",    "SEE",    "SEN",
97 	"SET",    "SEW",    "SHE",    "SHY",    "SIN",    "SIP",    "SIR",
98 	"SIS",    "SIT",    "SKI",    "SKY",    "SLY",    "SO",     "SOB",
99 	"SOD",    "SON",    "SOP",    "SOW",    "SOY",    "SPA",    "SPY",
100 	"SUB",    "SUD",    "SUE",    "SUM",    "SUN",    "SUP",    "TAB",
101 	"TAD",    "TAG",    "TAN",    "TAP",    "TAR",    "TEA",    "TED",
102 	"TEE",    "TEN",    "THE",    "THY",    "TIC",    "TIE",    "TIM",
103 	"TIN",    "TIP",    "TO",     "TOE",    "TOG",    "TOM",    "TON",
104 	"TOO",    "TOP",    "TOW",    "TOY",    "TRY",    "TUB",    "TUG",
105 	"TUM",    "TUN",    "TWO",    "UN",     "UP",     "US",     "USE",
106 	"VAN",    "VAT",    "VET",    "VIE",    "WAD",    "WAG",    "WAR",
107 	"WAS",    "WAY",    "WE",     "WEB",    "WED",    "WEE",    "WET",
108 	"WHO",    "WHY",    "WIN",    "WIT",    "WOK",    "WON",    "WOO",
109 	"WOW",    "WRY",    "WU",     "YAM",    "YAP",    "YAW",    "YE",
110 	"YEA",    "YES",    "YET",    "YOU",    "ABED",   "ABEL",   "ABET",
111 	"ABLE",   "ABUT",   "ACHE",   "ACID",   "ACME",   "ACRE",   "ACTA",
112 	"ACTS",   "ADAM",   "ADDS",   "ADEN",   "AFAR",   "AFRO",   "AGEE",
113 	"AHEM",   "AHOY",   "AIDA",   "AIDE",   "AIDS",   "AIRY",   "AJAR",
114 	"AKIN",   "ALAN",   "ALEC",   "ALGA",   "ALIA",   "ALLY",   "ALMA",
115 	"ALOE",   "ALSO",   "ALTO",   "ALUM",   "ALVA",   "AMEN",   "AMES",
116 	"AMID",   "AMMO",   "AMOK",   "AMOS",   "AMRA",   "ANDY",   "ANEW",
117 	"ANNA",   "ANNE",   "ANTE",   "ANTI",   "AQUA",   "ARAB",   "ARCH",
118 	"AREA",   "ARGO",   "ARID",   "ARMY",   "ARTS",   "ARTY",   "ASIA",
119 	"ASKS",   "ATOM",   "AUNT",   "AURA",   "AUTO",   "AVER",   "AVID",
120 	"AVIS",   "AVON",   "AVOW",   "AWAY",   "AWRY",   "BABE",   "BABY",
121 	"BACH",   "BACK",   "BADE",   "BAIL",   "BAIT",   "BAKE",   "BALD",
122 	"BALE",   "BALI",   "BALK",   "BALL",   "BALM",   "BAND",   "BANE",
123 	"BANG",   "BANK",   "BARB",   "BARD",   "BARE",   "BARK",   "BARN",
124 	"BARR",   "BASE",   "BASH",   "BASK",   "BASS",   "BATE",   "BATH",
125 	"BAWD",   "BAWL",   "BEAD",   "BEAK",   "BEAM",   "BEAN",   "BEAR",
126 	"BEAT",   "BEAU",   "BECK",   "BEEF",   "BEEN",   "BEER",   "BEET",
127 	"BELA",   "BELL",   "BELT",   "BEND",   "BENT",   "BERG",   "BERN",
128 	"BERT",   "BESS",   "BEST",   "BETA",   "BETH",   "BHOY",   "BIAS",
129 	"BIDE",   "BIEN",   "BILE",   "BILK",   "BILL",   "BIND",   "BING",
130 	"BIRD",   "BITE",   "BITS",   "BLAB",   "BLAT",   "BLED",   "BLEW",
131 	"BLOB",   "BLOC",   "BLOT",   "BLOW",   "BLUE",   "BLUM",   "BLUR",
132 	"BOAR",   "BOAT",   "BOCA",   "BOCK",   "BODE",   "BODY",   "BOGY",
133 	"BOHR",   "BOIL",   "BOLD",   "BOLO",   "BOLT",   "BOMB",   "BONA",
134 	"BOND",   "BONE",   "BONG",   "BONN",   "BONY",   "BOOK",   "BOOM",
135 	"BOON",   "BOOT",   "BORE",   "BORG",   "BORN",   "BOSE",   "BOSS",
136 	"BOTH",   "BOUT",   "BOWL",   "BOYD",   "BRAD",   "BRAE",   "BRAG",
137 	"BRAN",   "BRAY",   "BRED",   "BREW",   "BRIG",   "BRIM",   "BROW",
138 	"BUCK",   "BUDD",   "BUFF",   "BULB",   "BULK",   "BULL",   "BUNK",
139 	"BUNT",   "BUOY",   "BURG",   "BURL",   "BURN",   "BURR",   "BURT",
140 	"BURY",   "BUSH",   "BUSS",   "BUST",   "BUSY",   "BYTE",   "CADY",
141 	"CAFE",   "CAGE",   "CAIN",   "CAKE",   "CALF",   "CALL",   "CALM",
142 	"CAME",   "CANE",   "CANT",   "CARD",   "CARE",   "CARL",   "CARR",
143 	"CART",   "CASE",   "CASH",   "CASK",   "CAST",   "CAVE",   "CEIL",
144 	"CELL",   "CENT",   "CERN",   "CHAD",   "CHAR",   "CHAT",   "CHAW",
145 	"CHEF",   "CHEN",   "CHEW",   "CHIC",   "CHIN",   "CHOU",   "CHOW",
146 	"CHUB",   "CHUG",   "CHUM",   "CITE",   "CITY",   "CLAD",   "CLAM",
147 	"CLAN",   "CLAW",   "CLAY",   "CLOD",   "CLOG",   "CLOT",   "CLUB",
148 	"CLUE",   "COAL",   "COAT",   "COCA",   "COCK",   "COCO",   "CODA",
149 	"CODE",   "CODY",   "COED",   "COIL",   "COIN",   "COKE",   "COLA",
150 	"COLD",   "COLT",   "COMA",   "COMB",   "COME",   "COOK",   "COOL",
151 	"COON",   "COOT",   "CORD",   "CORE",   "CORK",   "CORN",   "COST",
152 	"COVE",   "COWL",   "CRAB",   "CRAG",   "CRAM",   "CRAY",   "CREW",
153 	"CRIB",   "CROW",   "CRUD",   "CUBA",   "CUBE",   "CUFF",   "CULL",
154 	"CULT",   "CUNY",   "CURB",   "CURD",   "CURE",   "CURL",   "CURT",
155 	"CUTS",   "DADE",   "DALE",   "DAME",   "DANA",   "DANE",   "DANG",
156 	"DANK",   "DARE",   "DARK",   "DARN",   "DART",   "DASH",   "DATA",
157 	"DATE",   "DAVE",   "DAVY",   "DAWN",   "DAYS",   "DEAD",   "DEAF",
158 	"DEAL",   "DEAN",   "DEAR",   "DEBT",   "DECK",   "DEED",   "DEEM",
159 	"DEER",   "DEFT",   "DEFY",   "DELL",   "DENT",   "DENY",   "DESK",
160 	"DIAL",   "DICE",   "DIED",   "DIET",   "DIME",   "DINE",   "DING",
161 	"DINT",   "DIRE",   "DIRT",   "DISC",   "DISH",   "DISK",   "DIVE",
162 	"DOCK",   "DOES",   "DOLE",   "DOLL",   "DOLT",   "DOME",   "DONE",
163 	"DOOM",   "DOOR",   "DORA",   "DOSE",   "DOTE",   "DOUG",   "DOUR",
164 	"DOVE",   "DOWN",   "DRAB",   "DRAG",   "DRAM",   "DRAW",   "DREW",
165 	"DRUB",   "DRUG",   "DRUM",   "DUAL",   "DUCK",   "DUCT",   "DUEL",
166 	"DUET",   "DUKE",   "DULL",   "DUMB",   "DUNE",   "DUNK",   "DUSK",
167 	"DUST",   "DUTY",   "EACH",   "EARL",   "EARN",   "EASE",   "EAST",
168 	"EASY",   "EBEN",   "ECHO",   "EDDY",   "EDEN",   "EDGE",   "EDGY",
169 	"EDIT",   "EDNA",   "EGAN",   "ELAN",   "ELBA",   "ELLA",   "ELSE",
170 	"EMIL",   "EMIT",   "EMMA",   "ENDS",   "ERIC",   "EROS",   "EVEN",
171 	"EVER",   "EVIL",   "EYED",   "FACE",   "FACT",   "FADE",   "FAIL",
172 	"FAIN",   "FAIR",   "FAKE",   "FALL",   "FAME",   "FANG",   "FARM",
173 	"FAST",   "FATE",   "FAWN",   "FEAR",   "FEAT",   "FEED",   "FEEL",
174 	"FEET",   "FELL",   "FELT",   "FEND",   "FERN",   "FEST",   "FEUD",
175 	"FIEF",   "FIGS",   "FILE",   "FILL",   "FILM",   "FIND",   "FINE",
176 	"FINK",   "FIRE",   "FIRM",   "FISH",   "FISK",   "FIST",   "FITS",
177 	"FIVE",   "FLAG",   "FLAK",   "FLAM",   "FLAT",   "FLAW",   "FLEA",
178 	"FLED",   "FLEW",   "FLIT",   "FLOC",   "FLOG",   "FLOW",   "FLUB",
179 	"FLUE",   "FOAL",   "FOAM",   "FOGY",   "FOIL",   "FOLD",   "FOLK",
180 	"FOND",   "FONT",   "FOOD",   "FOOL",   "FOOT",   "FORD",   "FORE",
181 	"FORK",   "FORM",   "FORT",   "FOSS",   "FOUL",   "FOUR",   "FOWL",
182 	"FRAU",   "FRAY",   "FRED",   "FREE",   "FRET",   "FREY",   "FROG",
183 	"FROM",   "FUEL",   "FULL",   "FUME",   "FUND",   "FUNK",   "FURY",
184 	"FUSE",   "FUSS",   "GAFF",   "GAGE",   "GAIL",   "GAIN",   "GAIT",
185 	"GALA",   "GALE",   "GALL",   "GALT",   "GAME",   "GANG",   "GARB",
186 	"GARY",   "GASH",   "GATE",   "GAUL",   "GAUR",   "GAVE",   "GAWK",
187 	"GEAR",   "GELD",   "GENE",   "GENT",   "GERM",   "GETS",   "GIBE",
188 	"GIFT",   "GILD",   "GILL",   "GILT",   "GINA",   "GIRD",   "GIRL",
189 	"GIST",   "GIVE",   "GLAD",   "GLEE",   "GLEN",   "GLIB",   "GLOB",
190 	"GLOM",   "GLOW",   "GLUE",   "GLUM",   "GLUT",   "GOAD",   "GOAL",
191 	"GOAT",   "GOER",   "GOES",   "GOLD",   "GOLF",   "GONE",   "GONG",
192 	"GOOD",   "GOOF",   "GORE",   "GORY",   "GOSH",   "GOUT",   "GOWN",
193 	"GRAB",   "GRAD",   "GRAY",   "GREG",   "GREW",   "GREY",   "GRID",
194 	"GRIM",   "GRIN",   "GRIT",   "GROW",   "GRUB",   "GULF",   "GULL",
195 	"GUNK",   "GURU",   "GUSH",   "GUST",   "GWEN",   "GWYN",   "HAAG",
196 	"HAAS",   "HACK",   "HAIL",   "HAIR",   "HALE",   "HALF",   "HALL",
197 	"HALO",   "HALT",   "HAND",   "HANG",   "HANK",   "HANS",   "HARD",
198 	"HARK",   "HARM",   "HART",   "HASH",   "HAST",   "HATE",   "HATH",
199 	"HAUL",   "HAVE",   "HAWK",   "HAYS",   "HEAD",   "HEAL",   "HEAR",
200 	"HEAT",   "HEBE",   "HECK",   "HEED",   "HEEL",   "HEFT",   "HELD",
201 	"HELL",   "HELM",   "HERB",   "HERD",   "HERE",   "HERO",   "HERS",
202 	"HESS",   "HEWN",   "HICK",   "HIDE",   "HIGH",   "HIKE",   "HILL",
203 	"HILT",   "HIND",   "HINT",   "HIRE",   "HISS",   "HIVE",   "HOBO",
204 	"HOCK",   "HOFF",   "HOLD",   "HOLE",   "HOLM",   "HOLT",   "HOME",
205 	"HONE",   "HONK",   "HOOD",   "HOOF",   "HOOK",   "HOOT",   "HORN",
206 	"HOSE",   "HOST",   "HOUR",   "HOVE",   "HOWE",   "HOWL",   "HOYT",
207 	"HUCK",   "HUED",   "HUFF",   "HUGE",   "HUGH",   "HUGO",   "HULK",
208 	"HULL",   "HUNK",   "HUNT",   "HURD",   "HURL",   "HURT",   "HUSH",
209 	"HYDE",   "HYMN",   "IBIS",   "ICON",   "IDEA",   "IDLE",   "IFFY",
210 	"INCA",   "INCH",   "INTO",   "IONS",   "IOTA",   "IOWA",   "IRIS",
211 	"IRMA",   "IRON",   "ISLE",   "ITCH",   "ITEM",   "IVAN",   "JACK",
212 	"JADE",   "JAIL",   "JAKE",   "JANE",   "JAVA",   "JEAN",   "JEFF",
213 	"JERK",   "JESS",   "JEST",   "JIBE",   "JILL",   "JILT",   "JIVE",
214 	"JOAN",   "JOBS",   "JOCK",   "JOEL",   "JOEY",   "JOHN",   "JOIN",
215 	"JOKE",   "JOLT",   "JOVE",   "JUDD",   "JUDE",   "JUDO",   "JUDY",
216 	"JUJU",   "JUKE",   "JULY",   "JUNE",   "JUNK",   "JUNO",   "JURY",
217 	"JUST",   "JUTE",   "KAHN",   "KALE",   "KANE",   "KANT",   "KARL",
218 	"KATE",   "KEEL",   "KEEN",   "KENO",   "KENT",   "KERN",   "KERR",
219 	"KEYS",   "KICK",   "KILL",   "KIND",   "KING",   "KIRK",   "KISS",
220 	"KITE",   "KLAN",   "KNEE",   "KNEW",   "KNIT",   "KNOB",   "KNOT",
221 	"KNOW",   "KOCH",   "KONG",   "KUDO",   "KURD",   "KURT",   "KYLE",
222 	"LACE",   "LACK",   "LACY",   "LADY",   "LAID",   "LAIN",   "LAIR",
223 	"LAKE",   "LAMB",   "LAME",   "LAND",   "LANE",   "LANG",   "LARD",
224 	"LARK",   "LASS",   "LAST",   "LATE",   "LAUD",   "LAVA",   "LAWN",
225 	"LAWS",   "LAYS",   "LEAD",   "LEAF",   "LEAK",   "LEAN",   "LEAR",
226 	"LEEK",   "LEER",   "LEFT",   "LEND",   "LENS",   "LENT",   "LEON",
227 	"LESK",   "LESS",   "LEST",   "LETS",   "LIAR",   "LICE",   "LICK",
228 	"LIED",   "LIEN",   "LIES",   "LIEU",   "LIFE",   "LIFT",   "LIKE",
229 	"LILA",   "LILT",   "LILY",   "LIMA",   "LIMB",   "LIME",   "LIND",
230 	"LINE",   "LINK",   "LINT",   "LION",   "LISA",   "LIST",   "LIVE",
231 	"LOAD",   "LOAF",   "LOAM",   "LOAN",   "LOCK",   "LOFT",   "LOGE",
232 	"LOIS",   "LOLA",   "LONE",   "LONG",   "LOOK",   "LOON",   "LOOT",
233 	"LORD",   "LORE",   "LOSE",   "LOSS",   "LOST",   "LOUD",   "LOVE",
234 	"LOWE",   "LUCK",   "LUCY",   "LUGE",   "LUKE",   "LULU",   "LUND",
235 	"LUNG",   "LURA",   "LURE",   "LURK",   "LUSH",   "LUST",   "LYLE",
236 	"LYNN",   "LYON",   "LYRA",   "MACE",   "MADE",   "MAGI",   "MAID",
237 	"MAIL",   "MAIN",   "MAKE",   "MALE",   "MALI",   "MALL",   "MALT",
238 	"MANA",   "MANN",   "MANY",   "MARC",   "MARE",   "MARK",   "MARS",
239 	"MART",   "MARY",   "MASH",   "MASK",   "MASS",   "MAST",   "MATE",
240 	"MATH",   "MAUL",   "MAYO",   "MEAD",   "MEAL",   "MEAN",   "MEAT",
241 	"MEEK",   "MEET",   "MELD",   "MELT",   "MEMO",   "MEND",   "MENU",
242 	"MERT",   "MESH",   "MESS",   "MICE",   "MIKE",   "MILD",   "MILE",
243 	"MILK",   "MILL",   "MILT",   "MIMI",   "MIND",   "MINE",   "MINI",
244 	"MINK",   "MINT",   "MIRE",   "MISS",   "MIST",   "MITE",   "MITT",
245 	"MOAN",   "MOAT",   "MOCK",   "MODE",   "MOLD",   "MOLE",   "MOLL",
246 	"MOLT",   "MONA",   "MONK",   "MONT",   "MOOD",   "MOON",   "MOOR",
247 	"MOOT",   "MORE",   "MORN",   "MORT",   "MOSS",   "MOST",   "MOTH",
248 	"MOVE",   "MUCH",   "MUCK",   "MUDD",   "MUFF",   "MULE",   "MULL",
249 	"MURK",   "MUSH",   "MUST",   "MUTE",   "MUTT",   "MYRA",   "MYTH",
250 	"NAGY",   "NAIL",   "NAIR",   "NAME",   "NARY",   "NASH",   "NAVE",
251 	"NAVY",   "NEAL",   "NEAR",   "NEAT",   "NECK",   "NEED",   "NEIL",
252 	"NELL",   "NEON",   "NERO",   "NESS",   "NEST",   "NEWS",   "NEWT",
253 	"NIBS",   "NICE",   "NICK",   "NILE",   "NINA",   "NINE",   "NOAH",
254 	"NODE",   "NOEL",   "NOLL",   "NONE",   "NOOK",   "NOON",   "NORM",
255 	"NOSE",   "NOTE",   "NOUN",   "NOVA",   "NUDE",   "NULL",   "NUMB",
256 	"OATH",   "OBEY",   "OBOE",   "ODIN",   "OHIO",   "OILY",   "OINT",
257 	"OKAY",   "OLAF",   "OLDY",   "OLGA",   "OLIN",   "OMAN",   "OMEN",
258 	"OMIT",   "ONCE",   "ONES",   "ONLY",   "ONTO",   "ONUS",   "ORAL",
259 	"ORGY",   "OSLO",   "OTIS",   "OTTO",   "OUCH",   "OUST",   "OUTS",
260 	"OVAL",   "OVEN",   "OVER",   "OWLY",   "OWNS",   "QUAD",   "QUIT",
261 	"QUOD",   "RACE",   "RACK",   "RACY",   "RAFT",   "RAGE",   "RAID",
262 	"RAIL",   "RAIN",   "RAKE",   "RANK",   "RANT",   "RARE",   "RASH",
263 	"RATE",   "RAVE",   "RAYS",   "READ",   "REAL",   "REAM",   "REAR",
264 	"RECK",   "REED",   "REEF",   "REEK",   "REEL",   "REID",   "REIN",
265 	"RENA",   "REND",   "RENT",   "REST",   "RICE",   "RICH",   "RICK",
266 	"RIDE",   "RIFT",   "RILL",   "RIME",   "RING",   "RINK",   "RISE",
267 	"RISK",   "RITE",   "ROAD",   "ROAM",   "ROAR",   "ROBE",   "ROCK",
268 	"RODE",   "ROIL",   "ROLL",   "ROME",   "ROOD",   "ROOF",   "ROOK",
269 	"ROOM",   "ROOT",   "ROSA",   "ROSE",   "ROSS",   "ROSY",   "ROTH",
270 	"ROUT",   "ROVE",   "ROWE",   "ROWS",   "RUBE",   "RUBY",   "RUDE",
271 	"RUDY",   "RUIN",   "RULE",   "RUNG",   "RUNS",   "RUNT",   "RUSE",
272 	"RUSH",   "RUSK",   "RUSS",   "RUST",   "RUTH",   "SACK",   "SAFE",
273 	"SAGE",   "SAID",   "SAIL",   "SALE",   "SALK",   "SALT",   "SAME",
274 	"SAND",   "SANE",   "SANG",   "SANK",   "SARA",   "SAUL",   "SAVE",
275 	"SAYS",   "SCAN",   "SCAR",   "SCAT",   "SCOT",   "SEAL",   "SEAM",
276 	"SEAR",   "SEAT",   "SEED",   "SEEK",   "SEEM",   "SEEN",   "SEES",
277 	"SELF",   "SELL",   "SEND",   "SENT",   "SETS",   "SEWN",   "SHAG",
278 	"SHAM",   "SHAW",   "SHAY",   "SHED",   "SHIM",   "SHIN",   "SHOD",
279 	"SHOE",   "SHOT",   "SHOW",   "SHUN",   "SHUT",   "SICK",   "SIDE",
280 	"SIFT",   "SIGH",   "SIGN",   "SILK",   "SILL",   "SILO",   "SILT",
281 	"SINE",   "SING",   "SINK",   "SIRE",   "SITE",   "SITS",   "SITU",
282 	"SKAT",   "SKEW",   "SKID",   "SKIM",   "SKIN",   "SKIT",   "SLAB",
283 	"SLAM",   "SLAT",   "SLAY",   "SLED",   "SLEW",   "SLID",   "SLIM",
284 	"SLIT",   "SLOB",   "SLOG",   "SLOT",   "SLOW",   "SLUG",   "SLUM",
285 	"SLUR",   "SMOG",   "SMUG",   "SNAG",   "SNOB",   "SNOW",   "SNUB",
286 	"SNUG",   "SOAK",   "SOAR",   "SOCK",   "SODA",   "SOFA",   "SOFT",
287 	"SOIL",   "SOLD",   "SOME",   "SONG",   "SOON",   "SOOT",   "SORE",
288 	"SORT",   "SOUL",   "SOUR",   "SOWN",   "STAB",   "STAG",   "STAN",
289 	"STAR",   "STAY",   "STEM",   "STEW",   "STIR",   "STOW",   "STUB",
290 	"STUN",   "SUCH",   "SUDS",   "SUIT",   "SULK",   "SUMS",   "SUNG",
291 	"SUNK",   "SURE",   "SURF",   "SWAB",   "SWAG",   "SWAM",   "SWAN",
292 	"SWAT",   "SWAY",   "SWIM",   "SWUM",   "TACK",   "TACT",   "TAIL",
293 	"TAKE",   "TALE",   "TALK",   "TALL",   "TANK",   "TASK",   "TATE",
294 	"TAUT",   "TEAL",   "TEAM",   "TEAR",   "TECH",   "TEEM",   "TEEN",
295 	"TEET",   "TELL",   "TEND",   "TENT",   "TERM",   "TERN",   "TESS",
296 	"TEST",   "THAN",   "THAT",   "THEE",   "THEM",   "THEN",   "THEY",
297 	"THIN",   "THIS",   "THUD",   "THUG",   "TICK",   "TIDE",   "TIDY",
298 	"TIED",   "TIER",   "TILE",   "TILL",   "TILT",   "TIME",   "TINA",
299 	"TINE",   "TINT",   "TINY",   "TIRE",   "TOAD",   "TOGO",   "TOIL",
300 	"TOLD",   "TOLL",   "TONE",   "TONG",   "TONY",   "TOOK",   "TOOL",
301 	"TOOT",   "TORE",   "TORN",   "TOTE",   "TOUR",   "TOUT",   "TOWN",
302 	"TRAG",   "TRAM",   "TRAY",   "TREE",   "TREK",   "TRIG",   "TRIM",
303 	"TRIO",   "TROD",   "TROT",   "TROY",   "TRUE",   "TUBA",   "TUBE",
304 	"TUCK",   "TUFT",   "TUNA",   "TUNE",   "TUNG",   "TURF",   "TURN",
305 	"TUSK",   "TWIG",   "TWIN",   "TWIT",   "ULAN",   "UNIT",   "URGE",
306 	"USED",   "USER",   "USES",   "UTAH",   "VAIL",   "VAIN",   "VALE",
307 	"VARY",   "VASE",   "VAST",   "VEAL",   "VEDA",   "VEIL",   "VEIN",
308 	"VEND",   "VENT",   "VERB",   "VERY",   "VETO",   "VICE",   "VIEW",
309 	"VINE",   "VISE",   "VOID",   "VOLT",   "VOTE",   "WACK",   "WADE",
310 	"WAGE",   "WAIL",   "WAIT",   "WAKE",   "WALE",   "WALK",   "WALL",
311 	"WALT",   "WAND",   "WANE",   "WANG",   "WANT",   "WARD",   "WARM",
312 	"WARN",   "WART",   "WASH",   "WAST",   "WATS",   "WATT",   "WAVE",
313 	"WAVY",   "WAYS",   "WEAK",   "WEAL",   "WEAN",   "WEAR",   "WEED",
314 	"WEEK",   "WEIR",   "WELD",   "WELL",   "WELT",   "WENT",   "WERE",
315 	"WERT",   "WEST",   "WHAM",   "WHAT",   "WHEE",   "WHEN",   "WHET",
316 	"WHOA",   "WHOM",   "WICK",   "WIFE",   "WILD",   "WILL",   "WIND",
317 	"WINE",   "WING",   "WINK",   "WINO",   "WIRE",   "WISE",   "WISH",
318 	"WITH",   "WOLF",   "WONT",   "WOOD",   "WOOL",   "WORD",   "WORE",
319 	"WORK",   "WORM",   "WORN",   "WOVE",   "WRIT",   "WYNN",   "YALE",
320 	"YANG",   "YANK",   "YARD",   "YARN",   "YAWL",   "YAWN",   "YEAH",
321 	"YEAR",   "YELL",   "YOGA",   "YOKE"
322 };
323 
324 /*
325  * Encode 8 bytes in 'c' as a string of 6 four-letter English words separated
326  * by spaces.  The 'out' pointer must have at least 30 bytes for storage.
327  */
328 char *
btoe(char * engout,char * c)329 btoe(char *engout, char *c)
330 {
331 	char cp[10];	/* add in room for the parity 2 bits + extract() slop */
332 	int p, i, indices[6];
333 
334 	/* workaround for extract() reads beyond end of data */
335 	(void)memset(cp, 0, sizeof(cp));
336 	(void)memcpy(cp, c, 8);
337 
338 	/* compute parity */
339 	for (p = 0, i = 0; i < 64; i += 2)
340 		p += extract(cp, i, 2);
341 
342 	cp[8] = (char)p << 6;
343 
344 	indices[0] = extract(cp, 0, 11);
345 	indices[1] = extract(cp, 11, 11);
346 	indices[2] = extract(cp, 22, 11);
347 	indices[3] = extract(cp, 33, 11);
348 	indices[4] = extract(cp, 44, 11);
349 	indices[5] = extract(cp, 55, 11);
350 
351 	snprintf(engout, 30, "%.4s %.4s %.4s %.4s %.4s %.4s", Wp[indices[0]],
352 	    Wp[indices[1]], Wp[indices[2]], Wp[indices[3]],
353 	    Wp[indices[4]], Wp[indices[5]]);
354 
355 	return(engout);
356 }
357 
358 /*
359  * Converts the 6 space-separated english words in 'e' to binary form.
360  * The 'out' variable must be at least SKEY_BINKEY_SIZE bytes in size.
361  * returns 1 OK - all good words and parity is OK
362  *         0 word not in data base
363  *        -1 badly formed in put ie > 4 char word
364  *        -2 words OK but parity is wrong
365  */
366 int
etob(char * out,char * e)367 etob(char *out, char *e)
368 {
369 	char *word;
370 	int i, p, v, l, low, high;
371 	char b[SKEY_BINKEY_SIZE+1];
372 	char input[36];
373 	char *last;
374 
375 	if (e == NULL)
376 		return(-1);
377 
378 	(void)strlcpy(input, e, sizeof(input));
379 	(void)memset(b, 0, sizeof(b));
380 	(void)memset(out, 0, SKEY_BINKEY_SIZE);
381 	for (i = 0, p = 0; i < 6; i++, p += 11) {
382 		if ((word = strtok_r(i == 0 ? input : NULL, " ", &last)) == NULL)
383 			return(-1);
384 
385 		l = strlen(word);
386 		if (l > 4 || l < 1) {
387 			return(-1);
388 		} else if (l < 4) {
389 			low = 0;
390 			high = 570;
391 		} else {
392 			low = 571;
393 			high = 2047;
394 		}
395 		standard(word);
396 
397 		if ((v = wsrch(word, low, high)) < 0)
398 			return(0);
399 
400 		insert(b, v, p, 11);
401 	}
402 
403 	/* now check the parity of what we got */
404 	for (p = 0, i = 0; i < 64; i += 2)
405 		p += extract(b, i, 2);
406 
407 	if ((p & 3) != extract(b, 64, 2))
408 		return(-2);
409 
410 	(void)memcpy(out, b, SKEY_BINKEY_SIZE);
411 
412 	return(1);
413 }
414 
415 /*
416  * Format 8 bytes as a series of four 16-bit hex digits.
417  * The 'out' pointer must have at least 20 bytes for storage.
418  */
419 char *
put8(char * out,char * s)420 put8(char *out, char *s)
421 {
422 	(void)snprintf(out, 20, "%02X%02X %02X%02X %02X%02X %02X%02X",
423 			s[0] & 0xff, s[1] & 0xff, s[2] & 0xff,
424 			s[3] & 0xff, s[4] & 0xff, s[5] & 0xff,
425 			s[6] & 0xff, s[7] & 0xff);
426 	return(out);
427 }
428 
429 /* Internal subroutines for word encoding/decoding */
430 
431 /* Dictionary binary search */
432 static int
wsrch(char * w,int low,int high)433 wsrch(char *w, int low, int high)
434 {
435 	int i, j;
436 
437 	for (;;) {
438 		i = (low + high) / 2;
439 
440 		if ((j = strncmp(w, Wp[i], 4)) == 0)
441 			return(i);			/* Found it */
442 
443 		if (high == low + 1) {
444 			/* Avoid effects of integer truncation in /2 */
445 			if (strncmp(w, Wp[high], 4) == 0)
446 				return(high);
447 			else
448 				return(-1);
449 		}
450 
451 		if (low >= high)
452 			return(-1);	/* I don't *think* this can happen... */
453 		if (j < 0)
454 			high = i;	/* Search lower half */
455 		else
456 			low = i;	/* Search upper half */
457 	}
458 }
459 
460 static void
insert(char * s,int x,int start,int length)461 insert(char *s, int x, int start, int length)
462 {
463 	unsigned char cl;
464 	unsigned char cc;
465 	unsigned char cr;
466 	unsigned int y;
467 	int shift;
468 
469 	assert(length <= 11);
470 	assert(start >= 0);
471 	assert(length >= 0);
472 	assert(start + length <= 66);
473 
474 	shift = ((8 - ((start + length) % 8)) % 8);
475 	y = x << shift;
476 	cl = (y >> 16) & 0xff;
477 	cc = (y >> 8) & 0xff;
478 	cr = y & 0xff;
479 	if (shift + length > 16) {
480 		s[start / 8] |= cl;
481 		s[start / 8 + 1] |= cc;
482 		s[start / 8 + 2] |= cr;
483 	} else if (shift + length > 8) {
484 		s[start / 8] |= cc;
485 		s[start / 8 + 1] |= cr;
486 	} else {
487 		s[start / 8] |= cr;
488  	}
489 }
490 
491 static void
standard(char * word)492 standard(char *word)
493 {
494 	while (*word) {
495 		if (!isascii((unsigned char)*word))
496 			break;
497 		if (islower((unsigned char)*word))
498 			*word = toupper((unsigned char)*word);
499 		if (*word == '1')
500 			*word = 'L';
501 		if (*word == '0')
502 			*word = 'O';
503 		if (*word == '5')
504 			*word = 'S';
505 		word++;
506 	}
507 }
508 
509 /* Extract 'length' bits from the char array 's' starting with bit 'start' */
510 static unsigned int
extract(char * s,int start,int length)511 extract(char *s, int start, int length)
512 {
513 	unsigned char cl;
514 	unsigned char cc;
515 	unsigned char cr;
516 	unsigned int x;
517 
518 	assert(length <= 11);
519 	assert(start >= 0);
520 	assert(length >= 0);
521 	assert(start + length <= 66);
522 
523 	cl = s[start / 8];
524 	cc = s[start / 8 + 1];
525 	cr = s[start / 8 + 2];
526 	x = ((int)(cl << 8 | cc) << 8 | cr);
527 	x = x >> (24 - (length + (start % 8)));
528 	x = (x & (0xffff >> (16 - length)));
529 
530 	return(x);
531 }
532