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