aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/libotr/libotr-3.2.0/src
diff options
context:
space:
mode:
authorJay Threeth2011-04-04 11:48:26 -0700
committerJay Threeth2011-04-04 11:48:26 -0700
commit3c9cc506f741b980565ff5b3b001cd8b6ee36b12 (patch)
treecb862c57b3d5f74177cde3bd962a53fc377166f6 /linden/indra/libotr/libotr-3.2.0/src
parentbuild fixes, might build on linux now (diff)
downloadmeta-impy-3c9cc506f741b980565ff5b3b001cd8b6ee36b12.zip
meta-impy-3c9cc506f741b980565ff5b3b001cd8b6ee36b12.tar.gz
meta-impy-3c9cc506f741b980565ff5b3b001cd8b6ee36b12.tar.bz2
meta-impy-3c9cc506f741b980565ff5b3b001cd8b6ee36b12.tar.xz
add source to libraries, and cruft for building under windows
Diffstat (limited to 'linden/indra/libotr/libotr-3.2.0/src')
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/Makefile.am13
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/Makefile.in494
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/auth.c1413
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/auth.h157
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/b64.c249
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/b64.h57
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/context.c321
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/context.h179
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/dh.c466
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/dh.h119
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/mem.c163
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/mem.h25
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/message.c1455
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/message.h210
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/privkey-t.h39
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/privkey.c745
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/privkey.h112
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/proto.c998
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/proto.h153
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/serial.h85
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/sm.c929
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/sm.h83
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/tlv.c108
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/tlv.h70
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/userstate.c51
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/userstate.h45
-rwxr-xr-xlinden/indra/libotr/libotr-3.2.0/src/version.h29
27 files changed, 8768 insertions, 0 deletions
diff --git a/linden/indra/libotr/libotr-3.2.0/src/Makefile.am b/linden/indra/libotr/libotr-3.2.0/src/Makefile.am
new file mode 100755
index 0000000..c75fcbe
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/Makefile.am
@@ -0,0 +1,13 @@
1INCLUDES = @LIBGCRYPT_CFLAGS@
2
3lib_LTLIBRARIES = libotr.la
4
5libotr_la_SOURCES = privkey.c context.c proto.c b64.c dh.c mem.c message.c \
6 userstate.c tlv.c auth.c sm.c
7
8libotr_la_LDFLAGS = -version-info @LIBOTR_LIBTOOL_VERSION@ @LIBS@ @LIBGCRYPT_LIBS@
9
10otrincdir = $(includedir)/libotr
11
12otrinc_HEADERS = b64.h context.h dh.h mem.h message.h privkey.h proto.h \
13 version.h userstate.h tlv.h serial.h auth.h sm.h privkey-t.h
diff --git a/linden/indra/libotr/libotr-3.2.0/src/Makefile.in b/linden/indra/libotr/libotr-3.2.0/src/Makefile.in
new file mode 100755
index 0000000..5de6fb4
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/Makefile.in
@@ -0,0 +1,494 @@
1# Makefile.in generated by automake 1.9.6 from Makefile.am.
2# @configure_input@
3
4# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
5# 2003, 2004, 2005 Free Software Foundation, Inc.
6# This Makefile.in is free software; the Free Software Foundation
7# gives unlimited permission to copy and/or distribute it,
8# with or without modifications, as long as this notice is preserved.
9
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
12# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13# PARTICULAR PURPOSE.
14
15@SET_MAKE@
16
17
18srcdir = @srcdir@
19top_srcdir = @top_srcdir@
20VPATH = @srcdir@
21pkgdatadir = $(datadir)/@PACKAGE@
22pkglibdir = $(libdir)/@PACKAGE@
23pkgincludedir = $(includedir)/@PACKAGE@
24top_builddir = ..
25am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
26INSTALL = @INSTALL@
27install_sh_DATA = $(install_sh) -c -m 644
28install_sh_PROGRAM = $(install_sh) -c
29install_sh_SCRIPT = $(install_sh) -c
30INSTALL_HEADER = $(INSTALL_DATA)
31transform = $(program_transform_name)
32NORMAL_INSTALL = :
33PRE_INSTALL = :
34POST_INSTALL = :
35NORMAL_UNINSTALL = :
36PRE_UNINSTALL = :
37POST_UNINSTALL = :
38build_triplet = @build@
39host_triplet = @host@
40subdir = src
41DIST_COMMON = $(otrinc_HEADERS) $(srcdir)/Makefile.am \
42 $(srcdir)/Makefile.in
43ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
44am__aclocal_m4_deps = $(top_srcdir)/configure.ac
45am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
46 $(ACLOCAL_M4)
47mkinstalldirs = $(install_sh) -d
48CONFIG_HEADER = $(top_builddir)/config.h
49CONFIG_CLEAN_FILES =
50am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
51am__vpath_adj = case $$p in \
52 $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
53 *) f=$$p;; \
54 esac;
55am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
56am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(otrincdir)"
57libLTLIBRARIES_INSTALL = $(INSTALL)
58LTLIBRARIES = $(lib_LTLIBRARIES)
59libotr_la_LIBADD =
60am_libotr_la_OBJECTS = privkey.lo context.lo proto.lo b64.lo dh.lo \
61 mem.lo message.lo userstate.lo tlv.lo auth.lo sm.lo
62libotr_la_OBJECTS = $(am_libotr_la_OBJECTS)
63DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
64depcomp = $(SHELL) $(top_srcdir)/depcomp
65am__depfiles_maybe = depfiles
66COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
67 $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
68LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
69 $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
70 $(AM_CFLAGS) $(CFLAGS)
71CCLD = $(CC)
72LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
73 $(AM_LDFLAGS) $(LDFLAGS) -o $@
74SOURCES = $(libotr_la_SOURCES)
75DIST_SOURCES = $(libotr_la_SOURCES)
76otrincHEADERS_INSTALL = $(INSTALL_HEADER)
77HEADERS = $(otrinc_HEADERS)
78ETAGS = etags
79CTAGS = ctags
80DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
81ACLOCAL = @ACLOCAL@
82AMDEP_FALSE = @AMDEP_FALSE@
83AMDEP_TRUE = @AMDEP_TRUE@
84AMTAR = @AMTAR@
85AR = @AR@
86AUTOCONF = @AUTOCONF@
87AUTOHEADER = @AUTOHEADER@
88AUTOMAKE = @AUTOMAKE@
89AWK = @AWK@
90CC = @CC@
91CCDEPMODE = @CCDEPMODE@
92CFLAGS = @CFLAGS@
93CPP = @CPP@
94CPPFLAGS = @CPPFLAGS@
95CXX = @CXX@
96CXXCPP = @CXXCPP@
97CXXDEPMODE = @CXXDEPMODE@
98CXXFLAGS = @CXXFLAGS@
99CYGPATH_W = @CYGPATH_W@
100DEFS = @DEFS@
101DEPDIR = @DEPDIR@
102ECHO = @ECHO@
103ECHO_C = @ECHO_C@
104ECHO_N = @ECHO_N@
105ECHO_T = @ECHO_T@
106EGREP = @EGREP@
107EXEEXT = @EXEEXT@
108F77 = @F77@
109FFLAGS = @FFLAGS@
110INSTALL_DATA = @INSTALL_DATA@
111INSTALL_PROGRAM = @INSTALL_PROGRAM@
112INSTALL_SCRIPT = @INSTALL_SCRIPT@
113INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
114LDFLAGS = @LDFLAGS@
115LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
116LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
117LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
118LIBOBJS = @LIBOBJS@
119LIBOTR_LIBTOOL_VERSION = @LIBOTR_LIBTOOL_VERSION@
120LIBS = @LIBS@
121LIBTOOL = @LIBTOOL@
122LN_S = @LN_S@
123LTLIBOBJS = @LTLIBOBJS@
124MAKEINFO = @MAKEINFO@
125OBJEXT = @OBJEXT@
126PACKAGE = @PACKAGE@
127PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
128PACKAGE_NAME = @PACKAGE_NAME@
129PACKAGE_STRING = @PACKAGE_STRING@
130PACKAGE_TARNAME = @PACKAGE_TARNAME@
131PACKAGE_VERSION = @PACKAGE_VERSION@
132PATH_SEPARATOR = @PATH_SEPARATOR@
133RANLIB = @RANLIB@
134SET_MAKE = @SET_MAKE@
135SHELL = @SHELL@
136STRIP = @STRIP@
137VERSION = @VERSION@
138ac_ct_AR = @ac_ct_AR@
139ac_ct_CC = @ac_ct_CC@
140ac_ct_CXX = @ac_ct_CXX@
141ac_ct_F77 = @ac_ct_F77@
142ac_ct_RANLIB = @ac_ct_RANLIB@
143ac_ct_STRIP = @ac_ct_STRIP@
144am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
145am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
146am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
147am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
148am__include = @am__include@
149am__leading_dot = @am__leading_dot@
150am__quote = @am__quote@
151am__tar = @am__tar@
152am__untar = @am__untar@
153bindir = @bindir@
154build = @build@
155build_alias = @build_alias@
156build_cpu = @build_cpu@
157build_os = @build_os@
158build_vendor = @build_vendor@
159datadir = @datadir@
160exec_prefix = @exec_prefix@
161host = @host@
162host_alias = @host_alias@
163host_cpu = @host_cpu@
164host_os = @host_os@
165host_vendor = @host_vendor@
166includedir = @includedir@
167infodir = @infodir@
168install_sh = @install_sh@
169libdir = @libdir@
170libexecdir = @libexecdir@
171localstatedir = @localstatedir@
172mandir = @mandir@
173mkdir_p = @mkdir_p@
174oldincludedir = @oldincludedir@
175prefix = @prefix@
176program_transform_name = @program_transform_name@
177sbindir = @sbindir@
178sharedstatedir = @sharedstatedir@
179sysconfdir = @sysconfdir@
180target_alias = @target_alias@
181INCLUDES = @LIBGCRYPT_CFLAGS@
182lib_LTLIBRARIES = libotr.la
183libotr_la_SOURCES = privkey.c context.c proto.c b64.c dh.c mem.c message.c \
184 userstate.c tlv.c auth.c sm.c
185
186libotr_la_LDFLAGS = -version-info @LIBOTR_LIBTOOL_VERSION@ @LIBS@ @LIBGCRYPT_LIBS@
187otrincdir = $(includedir)/libotr
188otrinc_HEADERS = b64.h context.h dh.h mem.h message.h privkey.h proto.h \
189 version.h userstate.h tlv.h serial.h auth.h sm.h privkey-t.h
190
191all: all-am
192
193.SUFFIXES:
194.SUFFIXES: .c .lo .o .obj
195$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
196 @for dep in $?; do \
197 case '$(am__configure_deps)' in \
198 *$$dep*) \
199 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
200 && exit 0; \
201 exit 1;; \
202 esac; \
203 done; \
204 echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
205 cd $(top_srcdir) && \
206 $(AUTOMAKE) --gnu src/Makefile
207.PRECIOUS: Makefile
208Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
209 @case '$?' in \
210 *config.status*) \
211 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
212 *) \
213 echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
214 cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
215 esac;
216
217$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
218 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
219
220$(top_srcdir)/configure: $(am__configure_deps)
221 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
222$(ACLOCAL_M4): $(am__aclocal_m4_deps)
223 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
224install-libLTLIBRARIES: $(lib_LTLIBRARIES)
225 @$(NORMAL_INSTALL)
226 test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
227 @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
228 if test -f $$p; then \
229 f=$(am__strip_dir) \
230 echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
231 $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
232 else :; fi; \
233 done
234
235uninstall-libLTLIBRARIES:
236 @$(NORMAL_UNINSTALL)
237 @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
238 p=$(am__strip_dir) \
239 echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
240 $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
241 done
242
243clean-libLTLIBRARIES:
244 -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
245 @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
246 dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
247 test "$$dir" != "$$p" || dir=.; \
248 echo "rm -f \"$${dir}/so_locations\""; \
249 rm -f "$${dir}/so_locations"; \
250 done
251libotr.la: $(libotr_la_OBJECTS) $(libotr_la_DEPENDENCIES)
252 $(LINK) -rpath $(libdir) $(libotr_la_LDFLAGS) $(libotr_la_OBJECTS) $(libotr_la_LIBADD) $(LIBS)
253
254mostlyclean-compile:
255 -rm -f *.$(OBJEXT)
256
257distclean-compile:
258 -rm -f *.tab.c
259
260@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth.Plo@am__quote@
261@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/b64.Plo@am__quote@
262@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/context.Plo@am__quote@
263@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dh.Plo@am__quote@
264@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Plo@am__quote@
265@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Plo@am__quote@
266@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/privkey.Plo@am__quote@
267@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto.Plo@am__quote@
268@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sm.Plo@am__quote@
269@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tlv.Plo@am__quote@
270@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/userstate.Plo@am__quote@
271
272.c.o:
273@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
274@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
275@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
276@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
277@am__fastdepCC_FALSE@ $(COMPILE) -c $<
278
279.c.obj:
280@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
281@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
282@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
283@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
284@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
285
286.c.lo:
287@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
288@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
289@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
290@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
291@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
292
293mostlyclean-libtool:
294 -rm -f *.lo
295
296clean-libtool:
297 -rm -rf .libs _libs
298
299distclean-libtool:
300 -rm -f libtool
301uninstall-info-am:
302install-otrincHEADERS: $(otrinc_HEADERS)
303 @$(NORMAL_INSTALL)
304 test -z "$(otrincdir)" || $(mkdir_p) "$(DESTDIR)$(otrincdir)"
305 @list='$(otrinc_HEADERS)'; for p in $$list; do \
306 if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
307 f=$(am__strip_dir) \
308 echo " $(otrincHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(otrincdir)/$$f'"; \
309 $(otrincHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(otrincdir)/$$f"; \
310 done
311
312uninstall-otrincHEADERS:
313 @$(NORMAL_UNINSTALL)
314 @list='$(otrinc_HEADERS)'; for p in $$list; do \
315 f=$(am__strip_dir) \
316 echo " rm -f '$(DESTDIR)$(otrincdir)/$$f'"; \
317 rm -f "$(DESTDIR)$(otrincdir)/$$f"; \
318 done
319
320ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
321 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
322 unique=`for i in $$list; do \
323 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
324 done | \
325 $(AWK) ' { files[$$0] = 1; } \
326 END { for (i in files) print i; }'`; \
327 mkid -fID $$unique
328tags: TAGS
329
330TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
331 $(TAGS_FILES) $(LISP)
332 tags=; \
333 here=`pwd`; \
334 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
335 unique=`for i in $$list; do \
336 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
337 done | \
338 $(AWK) ' { files[$$0] = 1; } \
339 END { for (i in files) print i; }'`; \
340 if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
341 test -n "$$unique" || unique=$$empty_fix; \
342 $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
343 $$tags $$unique; \
344 fi
345ctags: CTAGS
346CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
347 $(TAGS_FILES) $(LISP)
348 tags=; \
349 here=`pwd`; \
350 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
351 unique=`for i in $$list; do \
352 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
353 done | \
354 $(AWK) ' { files[$$0] = 1; } \
355 END { for (i in files) print i; }'`; \
356 test -z "$(CTAGS_ARGS)$$tags$$unique" \
357 || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
358 $$tags $$unique
359
360GTAGS:
361 here=`$(am__cd) $(top_builddir) && pwd` \
362 && cd $(top_srcdir) \
363 && gtags -i $(GTAGS_ARGS) $$here
364
365distclean-tags:
366 -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
367
368distdir: $(DISTFILES)
369 @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
370 topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
371 list='$(DISTFILES)'; for file in $$list; do \
372 case $$file in \
373 $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
374 $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
375 esac; \
376 if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
377 dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
378 if test "$$dir" != "$$file" && test "$$dir" != "."; then \
379 dir="/$$dir"; \
380 $(mkdir_p) "$(distdir)$$dir"; \
381 else \
382 dir=''; \
383 fi; \
384 if test -d $$d/$$file; then \
385 if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
386 cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
387 fi; \
388 cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
389 else \
390 test -f $(distdir)/$$file \
391 || cp -p $$d/$$file $(distdir)/$$file \
392 || exit 1; \
393 fi; \
394 done
395check-am: all-am
396check: check-am
397all-am: Makefile $(LTLIBRARIES) $(HEADERS)
398installdirs:
399 for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(otrincdir)"; do \
400 test -z "$$dir" || $(mkdir_p) "$$dir"; \
401 done
402install: install-am
403install-exec: install-exec-am
404install-data: install-data-am
405uninstall: uninstall-am
406
407install-am: all-am
408 @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
409
410installcheck: installcheck-am
411install-strip:
412 $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
413 install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
414 `test -z '$(STRIP)' || \
415 echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
416mostlyclean-generic:
417
418clean-generic:
419
420distclean-generic:
421 -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
422
423maintainer-clean-generic:
424 @echo "This command is intended for maintainers to use"
425 @echo "it deletes files that may require special tools to rebuild."
426clean: clean-am
427
428clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
429 mostlyclean-am
430
431distclean: distclean-am
432 -rm -rf ./$(DEPDIR)
433 -rm -f Makefile
434distclean-am: clean-am distclean-compile distclean-generic \
435 distclean-libtool distclean-tags
436
437dvi: dvi-am
438
439dvi-am:
440
441html: html-am
442
443info: info-am
444
445info-am:
446
447install-data-am: install-otrincHEADERS
448
449install-exec-am: install-libLTLIBRARIES
450
451install-info: install-info-am
452
453install-man:
454
455installcheck-am:
456
457maintainer-clean: maintainer-clean-am
458 -rm -rf ./$(DEPDIR)
459 -rm -f Makefile
460maintainer-clean-am: distclean-am maintainer-clean-generic
461
462mostlyclean: mostlyclean-am
463
464mostlyclean-am: mostlyclean-compile mostlyclean-generic \
465 mostlyclean-libtool
466
467pdf: pdf-am
468
469pdf-am:
470
471ps: ps-am
472
473ps-am:
474
475uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES \
476 uninstall-otrincHEADERS
477
478.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
479 clean-libLTLIBRARIES clean-libtool ctags distclean \
480 distclean-compile distclean-generic distclean-libtool \
481 distclean-tags distdir dvi dvi-am html html-am info info-am \
482 install install-am install-data install-data-am install-exec \
483 install-exec-am install-info install-info-am \
484 install-libLTLIBRARIES install-man install-otrincHEADERS \
485 install-strip installcheck installcheck-am installdirs \
486 maintainer-clean maintainer-clean-generic mostlyclean \
487 mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
488 pdf pdf-am ps ps-am tags uninstall uninstall-am \
489 uninstall-info-am uninstall-libLTLIBRARIES \
490 uninstall-otrincHEADERS
491
492# Tell versions [3.59,3.63) of GNU make to not export all variables.
493# Otherwise a system limit (for SysV at least) may be exceeded.
494.NOEXPORT:
diff --git a/linden/indra/libotr/libotr-3.2.0/src/auth.c b/linden/indra/libotr/libotr-3.2.0/src/auth.c
new file mode 100755
index 0000000..e4445f6
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/auth.c
@@ -0,0 +1,1413 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/* system headers */
21#include <stdlib.h>
22#include <string.h>
23#include <assert.h>
24
25/* libotr headers */
26#include "b64.h"
27#include "privkey.h"
28#include "auth.h"
29#include "serial.h"
30
31/*
32 * Initialize the fields of an OtrlAuthInfo (already allocated).
33 */
34void otrl_auth_new(OtrlAuthInfo *auth)
35{
36 auth->authstate = OTRL_AUTHSTATE_NONE;
37 otrl_dh_keypair_init(&(auth->our_dh));
38 auth->our_keyid = 0;
39 auth->encgx = NULL;
40 auth->encgx_len = 0;
41 memset(auth->r, 0, 16);
42 memset(auth->hashgx, 0, 32);
43 auth->their_pub = NULL;
44 auth->their_keyid = 0;
45 auth->enc_c = NULL;
46 auth->enc_cp = NULL;
47 auth->mac_m1 = NULL;
48 auth->mac_m1p = NULL;
49 auth->mac_m2 = NULL;
50 auth->mac_m2p = NULL;
51 memset(auth->their_fingerprint, 0, 20);
52 auth->initiated = 0;
53 auth->protocol_version = 0;
54 memset(auth->secure_session_id, 0, 20);
55 auth->secure_session_id_len = 0;
56 auth->lastauthmsg = NULL;
57}
58
59/*
60 * Clear the fields of an OtrlAuthInfo (but leave it allocated).
61 */
62void otrl_auth_clear(OtrlAuthInfo *auth)
63{
64 auth->authstate = OTRL_AUTHSTATE_NONE;
65 otrl_dh_keypair_free(&(auth->our_dh));
66 auth->our_keyid = 0;
67 free(auth->encgx);
68 auth->encgx = NULL;
69 auth->encgx_len = 0;
70 memset(auth->r, 0, 16);
71 memset(auth->hashgx, 0, 32);
72 gcry_mpi_release(auth->their_pub);
73 auth->their_pub = NULL;
74 auth->their_keyid = 0;
75 gcry_cipher_close(auth->enc_c);
76 gcry_cipher_close(auth->enc_cp);
77 gcry_md_close(auth->mac_m1);
78 gcry_md_close(auth->mac_m1p);
79 gcry_md_close(auth->mac_m2);
80 gcry_md_close(auth->mac_m2p);
81 auth->enc_c = NULL;
82 auth->enc_cp = NULL;
83 auth->mac_m1 = NULL;
84 auth->mac_m1p = NULL;
85 auth->mac_m2 = NULL;
86 auth->mac_m2p = NULL;
87 memset(auth->their_fingerprint, 0, 20);
88 auth->initiated = 0;
89 auth->protocol_version = 0;
90 memset(auth->secure_session_id, 0, 20);
91 auth->secure_session_id_len = 0;
92 free(auth->lastauthmsg);
93 auth->lastauthmsg = NULL;
94}
95
96/*
97 * Start a fresh AKE (version 2) using the given OtrlAuthInfo. Generate
98 * a fresh DH keypair to use. If no error is returned, the message to
99 * transmit will be contained in auth->lastauthmsg.
100 */
101gcry_error_t otrl_auth_start_v2(OtrlAuthInfo *auth)
102{
103 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
104 const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
105 size_t npub;
106 gcry_cipher_hd_t enc = NULL;
107 unsigned char ctr[16];
108 unsigned char *buf, *bufp;
109 size_t buflen, lenp;
110
111 /* Clear out this OtrlAuthInfo and start over */
112 otrl_auth_clear(auth);
113 auth->initiated = 1;
114
115 otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
116 auth->our_keyid = 1;
117
118 /* Pick an encryption key */
119 gcry_randomize(auth->r, 16, GCRY_STRONG_RANDOM);
120
121 /* Allocate space for the encrypted g^x */
122 gcry_mpi_print(format, NULL, 0, &npub, auth->our_dh.pub);
123 auth->encgx = malloc(4+npub);
124 if (auth->encgx == NULL) goto memerr;
125 auth->encgx_len = 4+npub;
126 bufp = auth->encgx;
127 lenp = auth->encgx_len;
128 write_mpi(auth->our_dh.pub, npub, "g^x");
129 assert(lenp == 0);
130
131 /* Hash g^x */
132 gcry_md_hash_buffer(GCRY_MD_SHA256, auth->hashgx, auth->encgx,
133 auth->encgx_len);
134
135 /* Encrypt g^x using the key r */
136 err = gcry_cipher_open(&enc, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR,
137 GCRY_CIPHER_SECURE);
138 if (err) goto err;
139
140 err = gcry_cipher_setkey(enc, auth->r, 16);
141 if (err) goto err;
142
143 memset(ctr, 0, 16);
144 err = gcry_cipher_setctr(enc, ctr, 16);
145 if (err) goto err;
146
147 err = gcry_cipher_encrypt(enc, auth->encgx, auth->encgx_len, NULL, 0);
148 if (err) goto err;
149
150 gcry_cipher_close(enc);
151 enc = NULL;
152
153 /* Now serialize the message */
154 lenp = 3 + 4 + auth->encgx_len + 4 + 32;
155 bufp = malloc(lenp);
156 if (bufp == NULL) goto memerr;
157 buf = bufp;
158 buflen = lenp;
159
160 memmove(bufp, "\x00\x02\x02", 3); /* header */
161 debug_data("Header", bufp, 3);
162 bufp += 3; lenp -= 3;
163
164 /* Encrypted g^x */
165 write_int(auth->encgx_len);
166 debug_int("Enc gx len", bufp-4);
167 memmove(bufp, auth->encgx, auth->encgx_len);
168 debug_data("Enc gx", bufp, auth->encgx_len);
169 bufp += auth->encgx_len; lenp -= auth->encgx_len;
170
171 /* Hashed g^x */
172 write_int(32);
173 debug_int("hashgx len", bufp-4);
174 memmove(bufp, auth->hashgx, 32);
175 debug_data("hashgx", bufp, 32);
176 bufp += 32; lenp -= 32;
177
178 assert(lenp == 0);
179
180 auth->lastauthmsg = otrl_base64_otr_encode(buf, buflen);
181 free(buf);
182 if (auth->lastauthmsg == NULL) goto memerr;
183 auth->authstate = OTRL_AUTHSTATE_AWAITING_DHKEY;
184
185 return err;
186
187memerr:
188 err = gcry_error(GPG_ERR_ENOMEM);
189err:
190 otrl_auth_clear(auth);
191 gcry_cipher_close(enc);
192 return err;
193}
194
195/*
196 * Create a D-H Key Message using the our_dh value in the given auth,
197 * and store it in auth->lastauthmsg.
198 */
199static gcry_error_t create_key_message(OtrlAuthInfo *auth)
200{
201 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
202 const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
203 unsigned char *buf, *bufp;
204 size_t buflen, lenp;
205 size_t npub;
206
207 gcry_mpi_print(format, NULL, 0, &npub, auth->our_dh.pub);
208 buflen = 3 + 4 + npub;
209 buf = malloc(buflen);
210 if (buf == NULL) goto memerr;
211 bufp = buf;
212 lenp = buflen;
213
214 memmove(bufp, "\x00\x02\x0a", 3); /* header */
215 debug_data("Header", bufp, 3);
216 bufp += 3; lenp -= 3;
217
218 /* g^y */
219 write_mpi(auth->our_dh.pub, npub, "g^y");
220
221 assert(lenp == 0);
222
223 free(auth->lastauthmsg);
224 auth->lastauthmsg = otrl_base64_otr_encode(buf, buflen);
225 free(buf);
226 if (auth->lastauthmsg == NULL) goto memerr;
227
228 return err;
229
230memerr:
231 err = gcry_error(GPG_ERR_ENOMEM);
232 return err;
233}
234
235/*
236 * Handle an incoming D-H Commit Message. If no error is returned, the
237 * message to send will be left in auth->lastauthmsg. Generate a fresh
238 * keypair to use.
239 */
240gcry_error_t otrl_auth_handle_commit(OtrlAuthInfo *auth,
241 const char *commitmsg)
242{
243 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
244 unsigned char *buf = NULL, *bufp = NULL, *encbuf = NULL;
245 unsigned char hashbuf[32];
246 size_t buflen, lenp, enclen, hashlen;
247 int res;
248
249 res = otrl_base64_otr_decode(commitmsg, &buf, &buflen);
250 if (res == -1) goto memerr;
251 if (res == -2) goto invval;
252
253 bufp = buf;
254 lenp = buflen;
255
256 /* Header */
257 require_len(3);
258 if (memcmp(bufp, "\x00\x02\x02", 3)) goto invval;
259 bufp += 3; lenp -= 3;
260
261 /* Encrypted g^x */
262 read_int(enclen);
263 require_len(enclen);
264 encbuf = malloc(enclen);
265 if (encbuf == NULL && enclen > 0) goto memerr;
266 memmove(encbuf, bufp, enclen);
267 bufp += enclen; lenp -= enclen;
268
269 /* Hashed g^x */
270 read_int(hashlen);
271 if (hashlen != 32) goto invval;
272 require_len(32);
273 memmove(hashbuf, bufp, 32);
274 bufp += 32; lenp -= 32;
275
276 if (lenp != 0) goto invval;
277 free(buf);
278 buf = NULL;
279
280 switch(auth->authstate) {
281 case OTRL_AUTHSTATE_NONE:
282 case OTRL_AUTHSTATE_AWAITING_SIG:
283 case OTRL_AUTHSTATE_V1_SETUP:
284
285 /* Store the incoming information */
286 otrl_auth_clear(auth);
287 otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
288 auth->our_keyid = 1;
289 auth->encgx = encbuf;
290 encbuf = NULL;
291 auth->encgx_len = enclen;
292 memmove(auth->hashgx, hashbuf, 32);
293
294 /* Create a D-H Key Message */
295 err = create_key_message(auth);
296 if (err) goto err;
297 auth->authstate = OTRL_AUTHSTATE_AWAITING_REVEALSIG;
298
299 break;
300
301 case OTRL_AUTHSTATE_AWAITING_DHKEY:
302 /* We sent a D-H Commit Message, and we also received one
303 * back. Compare the hashgx values to see which one wins. */
304 if (memcmp(auth->hashgx, hashbuf, 32) > 0) {
305 /* Ours wins. Ignore the message we received, and just
306 * resend the same D-H Commit message again. */
307 free(encbuf);
308 encbuf = NULL;
309 } else {
310 /* Ours loses. Use the incoming parameters instead. */
311 otrl_auth_clear(auth);
312 otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
313 auth->our_keyid = 1;
314 auth->encgx = encbuf;
315 encbuf = NULL;
316 auth->encgx_len = enclen;
317 memmove(auth->hashgx, hashbuf, 32);
318
319 /* Create a D-H Key Message */
320 err = create_key_message(auth);
321 if (err) goto err;
322 auth->authstate = OTRL_AUTHSTATE_AWAITING_REVEALSIG;
323 }
324 break;
325 case OTRL_AUTHSTATE_AWAITING_REVEALSIG:
326 /* Use the incoming parameters, but just retransmit the old
327 * D-H Key Message. */
328 free(auth->encgx);
329 auth->encgx = encbuf;
330 encbuf = NULL;
331 auth->encgx_len = enclen;
332 memmove(auth->hashgx, hashbuf, 32);
333 break;
334 }
335
336 return err;
337
338invval:
339 err = gcry_error(GPG_ERR_INV_VALUE);
340 goto err;
341memerr:
342 err = gcry_error(GPG_ERR_ENOMEM);
343err:
344 free(buf);
345 free(encbuf);
346 return err;
347}
348
349/*
350 * Calculate the encrypted part of the Reveal Signature and Signature
351 * Messages, given a MAC key, an encryption key, two DH public keys, an
352 * authentication public key (contained in an OtrlPrivKey structure),
353 * and a keyid. If no error is returned, *authbufp will point to the
354 * result, and *authlenp will point to its length.
355 */
356static gcry_error_t calculate_pubkey_auth(unsigned char **authbufp,
357 size_t *authlenp, gcry_md_hd_t mackey, gcry_cipher_hd_t enckey,
358 gcry_mpi_t our_dh_pub, gcry_mpi_t their_dh_pub,
359 OtrlPrivKey *privkey, unsigned int keyid)
360{
361 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
362 const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
363 size_t ourpublen, theirpublen, totallen, lenp;
364 unsigned char *buf = NULL, *bufp = NULL;
365 unsigned char macbuf[32];
366 unsigned char *sigbuf = NULL;
367 size_t siglen;
368
369 /* How big are the DH public keys? */
370 gcry_mpi_print(format, NULL, 0, &ourpublen, our_dh_pub);
371 gcry_mpi_print(format, NULL, 0, &theirpublen, their_dh_pub);
372
373 /* How big is the total structure to be MAC'd? */
374 totallen = 4 + ourpublen + 4 + theirpublen + 2 + privkey->pubkey_datalen
375 + 4;
376 buf = malloc(totallen);
377 if (buf == NULL) goto memerr;
378
379 bufp = buf;
380 lenp = totallen;
381
382 /* Write the data to be MAC'd */
383 write_mpi(our_dh_pub, ourpublen, "Our DH pubkey");
384 write_mpi(their_dh_pub, theirpublen, "Their DH pubkey");
385 bufp[0] = ((privkey->pubkey_type) >> 8) & 0xff;
386 bufp[1] = (privkey->pubkey_type) & 0xff;
387 bufp += 2; lenp -= 2;
388 memmove(bufp, privkey->pubkey_data, privkey->pubkey_datalen);
389 debug_data("Pubkey", bufp, privkey->pubkey_datalen);
390 bufp += privkey->pubkey_datalen; lenp -= privkey->pubkey_datalen;
391 write_int(keyid);
392 debug_int("Keyid", bufp-4);
393
394 assert(lenp == 0);
395
396 /* Do the MAC */
397 gcry_md_reset(mackey);
398 gcry_md_write(mackey, buf, totallen);
399 memmove(macbuf, gcry_md_read(mackey, GCRY_MD_SHA256), 32);
400
401 free(buf);
402 buf = NULL;
403
404 /* Sign the MAC */
405 err = otrl_privkey_sign(&sigbuf, &siglen, privkey, macbuf, 32);
406 if (err) goto err;
407
408 /* Calculate the total size of the structure to be encrypted */
409 totallen = 2 + privkey->pubkey_datalen + 4 + siglen;
410 buf = malloc(totallen);
411 if (buf == NULL) goto memerr;
412 bufp = buf;
413 lenp = totallen;
414
415 /* Write the data to be encrypted */
416 bufp[0] = ((privkey->pubkey_type) >> 8) & 0xff;
417 bufp[1] = (privkey->pubkey_type) & 0xff;
418 bufp += 2; lenp -= 2;
419 memmove(bufp, privkey->pubkey_data, privkey->pubkey_datalen);
420 debug_data("Pubkey", bufp, privkey->pubkey_datalen);
421 bufp += privkey->pubkey_datalen; lenp -= privkey->pubkey_datalen;
422 write_int(keyid);
423 debug_int("Keyid", bufp-4);
424 memmove(bufp, sigbuf, siglen);
425 debug_data("Signature", bufp, siglen);
426 bufp += siglen; lenp -= siglen;
427 free(sigbuf);
428 sigbuf = NULL;
429
430 assert(lenp == 0);
431
432 /* Now do the encryption */
433 err = gcry_cipher_encrypt(enckey, buf, totallen, NULL, 0);
434 if (err) goto err;
435
436 *authbufp = buf;
437 buf = NULL;
438 *authlenp = totallen;
439
440 return err;
441memerr:
442 err = gcry_error(GPG_ERR_ENOMEM);
443err:
444 free(buf);
445 free(sigbuf);
446 return err;
447}
448
449/*
450 * Decrypt the authenticator in the Reveal Signature and Signature
451 * Messages, given a MAC key, and encryption key, and two DH public
452 * keys. The fingerprint of the received public key will get put into
453 * fingerprintbufp, and the received keyid will get put in *keyidp.
454 * The encrypted data pointed to by authbuf will be decrypted in place.
455 */
456static gcry_error_t check_pubkey_auth(unsigned char fingerprintbufp[20],
457 unsigned int *keyidp, unsigned char *authbuf, size_t authlen,
458 gcry_md_hd_t mackey, gcry_cipher_hd_t enckey,
459 gcry_mpi_t our_dh_pub, gcry_mpi_t their_dh_pub)
460{
461 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
462 const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
463 size_t ourpublen, theirpublen, totallen, lenp;
464 unsigned char *buf = NULL, *bufp = NULL;
465 unsigned char macbuf[32];
466 unsigned short pubkey_type;
467 gcry_mpi_t p,q,g,y;
468 gcry_sexp_t pubs = NULL;
469 unsigned int received_keyid;
470 unsigned char *fingerprintstart, *fingerprintend, *sigbuf;
471 size_t siglen;
472
473 /* Start by decrypting it */
474 err = gcry_cipher_decrypt(enckey, authbuf, authlen, NULL, 0);
475 if (err) goto err;
476
477 bufp = authbuf;
478 lenp = authlen;
479
480 /* Get the public key and calculate its fingerprint */
481 require_len(2);
482 pubkey_type = (bufp[0] << 8) + bufp[1];
483 bufp += 2; lenp -= 2;
484 if (pubkey_type != OTRL_PUBKEY_TYPE_DSA) goto invval;
485 fingerprintstart = bufp;
486 read_mpi(p);
487 read_mpi(q);
488 read_mpi(g);
489 read_mpi(y);
490 fingerprintend = bufp;
491 gcry_md_hash_buffer(GCRY_MD_SHA1, fingerprintbufp,
492 fingerprintstart, fingerprintend-fingerprintstart);
493 gcry_sexp_build(&pubs, NULL,
494 "(public-key (dsa (p %m)(q %m)(g %m)(y %m)))", p, q, g, y);
495 gcry_mpi_release(p);
496 gcry_mpi_release(q);
497 gcry_mpi_release(g);
498 gcry_mpi_release(y);
499
500 /* Get the keyid */
501 read_int(received_keyid);
502 if (received_keyid == 0) goto invval;
503
504 /* Get the signature */
505 sigbuf = bufp;
506 siglen = lenp;
507
508 /* How big are the DH public keys? */
509 gcry_mpi_print(format, NULL, 0, &ourpublen, our_dh_pub);
510 gcry_mpi_print(format, NULL, 0, &theirpublen, their_dh_pub);
511
512 /* Now calculate the message to be MAC'd. */
513 totallen = 4 + ourpublen + 4 + theirpublen + 2 +
514 (fingerprintend - fingerprintstart) + 4;
515 buf = malloc(totallen);
516 if (buf == NULL) goto memerr;
517
518 bufp = buf;
519 lenp = totallen;
520
521 write_mpi(their_dh_pub, theirpublen, "Their DH pubkey");
522 write_mpi(our_dh_pub, ourpublen, "Our DH pubkey");
523 bufp[0] = (pubkey_type >> 8) & 0xff;
524 bufp[1] = pubkey_type & 0xff;
525 bufp += 2; lenp -= 2;
526 memmove(bufp, fingerprintstart, fingerprintend - fingerprintstart);
527 debug_data("Pubkey", bufp, fingerprintend - fingerprintstart);
528 bufp += fingerprintend - fingerprintstart;
529 lenp -= fingerprintend - fingerprintstart;
530 write_int(received_keyid);
531 debug_int("Keyid", bufp-4);
532
533 assert(lenp == 0);
534
535 /* Do the MAC */
536 gcry_md_reset(mackey);
537 gcry_md_write(mackey, buf, totallen);
538 memmove(macbuf, gcry_md_read(mackey, GCRY_MD_SHA256), 32);
539
540 free(buf);
541 buf = NULL;
542
543 /* Verify the signature on the MAC */
544 err = otrl_privkey_verify(sigbuf, siglen, pubkey_type, pubs, macbuf, 32);
545 if (err) goto err;
546 gcry_sexp_release(pubs);
547 pubs = NULL;
548
549 /* Everything checked out */
550 *keyidp = received_keyid;
551
552 return err;
553invval:
554 err = gcry_error(GPG_ERR_INV_VALUE);
555 goto err;
556memerr:
557 err = gcry_error(GPG_ERR_ENOMEM);
558err:
559 free(buf);
560 gcry_sexp_release(pubs);
561 return err;
562}
563
564/*
565 * Create a Reveal Signature Message using the values in the given auth,
566 * and store it in auth->lastauthmsg. Use the given privkey to sign the
567 * message.
568 */
569static gcry_error_t create_revealsig_message(OtrlAuthInfo *auth,
570 OtrlPrivKey *privkey)
571{
572 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
573 unsigned char *buf = NULL, *bufp, *startmac;
574 size_t buflen, lenp;
575
576 unsigned char *authbuf = NULL;
577 size_t authlen;
578
579 /* Get the encrypted authenticator */
580 err = calculate_pubkey_auth(&authbuf, &authlen, auth->mac_m1, auth->enc_c,
581 auth->our_dh.pub, auth->their_pub, privkey, auth->our_keyid);
582 if (err) goto err;
583
584 buflen = 3 + 4 + 16 + 4 + authlen + 20;
585 buf = malloc(buflen);
586 if (buf == NULL) goto memerr;
587
588 bufp = buf;
589 lenp = buflen;
590
591 memmove(bufp, "\x00\x02\x11", 3); /* header */
592 debug_data("Header", bufp, 3);
593 bufp += 3; lenp -= 3;
594
595 /* r */
596 write_int(16);
597 memmove(bufp, auth->r, 16);
598 debug_data("r", bufp, 16);
599 bufp += 16; lenp -= 16;
600
601 /* Encrypted authenticator */
602 startmac = bufp;
603 write_int(authlen);
604 memmove(bufp, authbuf, authlen);
605 debug_data("auth", bufp, authlen);
606 bufp += authlen; lenp -= authlen;
607 free(authbuf);
608 authbuf = NULL;
609
610 /* MAC it, but only take the first 20 bytes */
611 gcry_md_reset(auth->mac_m2);
612 gcry_md_write(auth->mac_m2, startmac, bufp - startmac);
613 memmove(bufp, gcry_md_read(auth->mac_m2, GCRY_MD_SHA256), 20);
614 debug_data("MAC", bufp, 20);
615 bufp += 20; lenp -= 20;
616
617 assert(lenp == 0);
618
619 free(auth->lastauthmsg);
620 auth->lastauthmsg = otrl_base64_otr_encode(buf, buflen);
621 if (auth->lastauthmsg == NULL) goto memerr;
622 free(buf);
623 buf = NULL;
624
625 return err;
626
627memerr:
628 err = gcry_error(GPG_ERR_ENOMEM);
629err:
630 free(buf);
631 free(authbuf);
632 return err;
633}
634
635/*
636 * Create a Signature Message using the values in the given auth, and
637 * store it in auth->lastauthmsg. Use the given privkey to sign the
638 * message.
639 */
640static gcry_error_t create_signature_message(OtrlAuthInfo *auth,
641 OtrlPrivKey *privkey)
642{
643 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
644 unsigned char *buf = NULL, *bufp, *startmac;
645 size_t buflen, lenp;
646
647 unsigned char *authbuf = NULL;
648 size_t authlen;
649
650 /* Get the encrypted authenticator */
651 err = calculate_pubkey_auth(&authbuf, &authlen, auth->mac_m1p,
652 auth->enc_cp, auth->our_dh.pub, auth->their_pub, privkey,
653 auth->our_keyid);
654 if (err) goto err;
655
656 buflen = 3 + 4 + authlen + 20;
657 buf = malloc(buflen);
658 if (buf == NULL) goto memerr;
659
660 bufp = buf;
661 lenp = buflen;
662
663 memmove(bufp, "\x00\x02\x12", 3); /* header */
664 debug_data("Header", bufp, 3);
665 bufp += 3; lenp -= 3;
666
667 /* Encrypted authenticator */
668 startmac = bufp;
669 write_int(authlen);
670 memmove(bufp, authbuf, authlen);
671 debug_data("auth", bufp, authlen);
672 bufp += authlen; lenp -= authlen;
673 free(authbuf);
674 authbuf = NULL;
675
676 /* MAC it, but only take the first 20 bytes */
677 gcry_md_reset(auth->mac_m2p);
678 gcry_md_write(auth->mac_m2p, startmac, bufp - startmac);
679 memmove(bufp, gcry_md_read(auth->mac_m2p, GCRY_MD_SHA256), 20);
680 debug_data("MAC", bufp, 20);
681 bufp += 20; lenp -= 20;
682
683 assert(lenp == 0);
684
685 free(auth->lastauthmsg);
686 auth->lastauthmsg = otrl_base64_otr_encode(buf, buflen);
687 if (auth->lastauthmsg == NULL) goto memerr;
688 free(buf);
689 buf = NULL;
690
691 return err;
692
693memerr:
694 err = gcry_error(GPG_ERR_ENOMEM);
695err:
696 free(buf);
697 free(authbuf);
698 return err;
699}
700
701/*
702 * Handle an incoming D-H Key Message. If no error is returned, and
703 * *havemsgp is 1, the message to sent will be left in auth->lastauthmsg.
704 * Use the given private authentication key to sign messages.
705 */
706gcry_error_t otrl_auth_handle_key(OtrlAuthInfo *auth, const char *keymsg,
707 int *havemsgp, OtrlPrivKey *privkey)
708{
709 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
710 unsigned char *buf = NULL, *bufp = NULL;
711 size_t buflen, lenp;
712 gcry_mpi_t incoming_pub = NULL;
713 int res;
714
715 *havemsgp = 0;
716
717 res = otrl_base64_otr_decode(keymsg, &buf, &buflen);
718 if (res == -1) goto memerr;
719 if (res == -2) goto invval;
720
721 bufp = buf;
722 lenp = buflen;
723
724 /* Header */
725 if (memcmp(bufp, "\x00\x02\x0a", 3)) goto invval;
726 bufp += 3; lenp -= 3;
727
728 /* g^y */
729 read_mpi(incoming_pub);
730
731 if (lenp != 0) goto invval;
732 free(buf);
733 buf = NULL;
734
735 switch(auth->authstate) {
736 case OTRL_AUTHSTATE_AWAITING_DHKEY:
737 /* Store the incoming public key */
738 gcry_mpi_release(auth->their_pub);
739 auth->their_pub = incoming_pub;
740 incoming_pub = NULL;
741
742 /* Compute the encryption and MAC keys */
743 err = otrl_dh_compute_v2_auth_keys(&(auth->our_dh),
744 auth->their_pub, auth->secure_session_id,
745 &(auth->secure_session_id_len),
746 &(auth->enc_c), &(auth->enc_cp),
747 &(auth->mac_m1), &(auth->mac_m1p),
748 &(auth->mac_m2), &(auth->mac_m2p));
749 if (err) goto err;
750
751 /* Create the Reveal Signature Message */
752 err = create_revealsig_message(auth, privkey);
753 if (err) goto err;
754 *havemsgp = 1;
755 auth->authstate = OTRL_AUTHSTATE_AWAITING_SIG;
756
757 break;
758
759 case OTRL_AUTHSTATE_AWAITING_SIG:
760 if (gcry_mpi_cmp(incoming_pub, auth->their_pub) == 0) {
761 /* Retransmit the Reveal Signature Message */
762 *havemsgp = 1;
763 } else {
764 /* Ignore this message */
765 *havemsgp = 0;
766 }
767 break;
768 case OTRL_AUTHSTATE_NONE:
769 case OTRL_AUTHSTATE_AWAITING_REVEALSIG:
770 case OTRL_AUTHSTATE_V1_SETUP:
771 /* Ignore this message */
772 *havemsgp = 0;
773 break;
774 }
775
776 gcry_mpi_release(incoming_pub);
777 return err;
778
779invval:
780 err = gcry_error(GPG_ERR_INV_VALUE);
781 goto err;
782memerr:
783 err = gcry_error(GPG_ERR_ENOMEM);
784err:
785 free(buf);
786 gcry_mpi_release(incoming_pub);
787 return err;
788}
789
790/*
791 * Handle an incoming Reveal Signature Message. If no error is
792 * returned, and *havemsgp is 1, the message to be sent will be left in
793 * auth->lastauthmsg. Use the given private authentication key to sign
794 * messages. Call the auth_succeeded callback if authentication is
795 * successful.
796 */
797gcry_error_t otrl_auth_handle_revealsig(OtrlAuthInfo *auth,
798 const char *revealmsg, int *havemsgp, OtrlPrivKey *privkey,
799 gcry_error_t (*auth_succeeded)(const OtrlAuthInfo *auth, void *asdata),
800 void *asdata)
801{
802 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
803 unsigned char *buf = NULL, *bufp = NULL, *gxbuf = NULL;
804 unsigned char *authstart, *authend, *macstart;
805 size_t buflen, lenp, rlen, authlen;
806 gcry_cipher_hd_t enc = NULL;
807 gcry_mpi_t incoming_pub = NULL;
808 unsigned char ctr[16], hashbuf[32];
809 int res;
810
811 *havemsgp = 0;
812
813 res = otrl_base64_otr_decode(revealmsg, &buf, &buflen);
814 if (res == -1) goto memerr;
815 if (res == -2) goto invval;
816
817 bufp = buf;
818 lenp = buflen;
819
820 /* Header */
821 if (memcmp(bufp, "\x00\x02\x11", 3)) goto invval;
822 bufp += 3; lenp -= 3;
823
824 /* r */
825 read_int(rlen);
826 if (rlen != 16) goto invval;
827 require_len(rlen);
828 memmove(auth->r, bufp, rlen);
829 bufp += rlen; lenp -= rlen;
830
831 /* auth */
832 authstart = bufp;
833 read_int(authlen);
834 require_len(authlen);
835 bufp += authlen; lenp -= authlen;
836 authend = bufp;
837
838 /* MAC */
839 require_len(20);
840 macstart = bufp;
841 bufp += 20; lenp -= 20;
842
843 if (lenp != 0) goto invval;
844
845 switch(auth->authstate) {
846 case OTRL_AUTHSTATE_AWAITING_REVEALSIG:
847 gxbuf = malloc(auth->encgx_len);
848 if (auth->encgx_len && gxbuf == NULL) goto memerr;
849
850 /* Use r to decrypt the value of g^x we received earlier */
851 err = gcry_cipher_open(&enc, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR,
852 GCRY_CIPHER_SECURE);
853 if (err) goto err;
854
855 err = gcry_cipher_setkey(enc, auth->r, 16);
856 if (err) goto err;
857
858 memset(ctr, 0, 16);
859 err = gcry_cipher_setctr(enc, ctr, 16);
860 if (err) goto err;
861
862 err = gcry_cipher_decrypt(enc, gxbuf, auth->encgx_len,
863 auth->encgx, auth->encgx_len);
864 if (err) goto err;
865
866 gcry_cipher_close(enc);
867 enc = NULL;
868
869 /* Check the hash */
870 gcry_md_hash_buffer(GCRY_MD_SHA256, hashbuf, gxbuf,
871 auth->encgx_len);
872 if (memcmp(hashbuf, auth->hashgx, 32)) goto decfail;
873
874 /* Extract g^x */
875 bufp = gxbuf;
876 lenp = auth->encgx_len;
877
878 read_mpi(incoming_pub);
879 free(gxbuf);
880 gxbuf = NULL;
881
882 if (lenp != 0) goto invval;
883
884 gcry_mpi_release(auth->their_pub);
885 auth->their_pub = incoming_pub;
886 incoming_pub = NULL;
887
888 /* Compute the encryption and MAC keys */
889 err = otrl_dh_compute_v2_auth_keys(&(auth->our_dh),
890 auth->their_pub, auth->secure_session_id,
891 &(auth->secure_session_id_len),
892 &(auth->enc_c), &(auth->enc_cp),
893 &(auth->mac_m1), &(auth->mac_m1p),
894 &(auth->mac_m2), &(auth->mac_m2p));
895 if (err) goto err;
896
897 /* Check the MAC */
898 gcry_md_reset(auth->mac_m2);
899 gcry_md_write(auth->mac_m2, authstart, authend - authstart);
900 if (memcmp(macstart,
901 gcry_md_read(auth->mac_m2, GCRY_MD_SHA256),
902 20)) goto invval;
903
904 /* Check the auth */
905 err = check_pubkey_auth(auth->their_fingerprint,
906 &(auth->their_keyid), authstart + 4,
907 authend - authstart - 4, auth->mac_m1, auth->enc_c,
908 auth->our_dh.pub, auth->their_pub);
909 if (err) goto err;
910
911 authstart = NULL;
912 authend = NULL;
913 macstart = NULL;
914 free(buf);
915 buf = NULL;
916
917 /* Create the Signature Message */
918 err = create_signature_message(auth, privkey);
919 if (err) goto err;
920
921 /* No error? Then we've completed our end of the
922 * authentication. */
923 auth->protocol_version = 2;
924 auth->session_id_half = OTRL_SESSIONID_SECOND_HALF_BOLD;
925 if (auth_succeeded) err = auth_succeeded(auth, asdata);
926 *havemsgp = 1;
927 auth->our_keyid = 0;
928 auth->authstate = OTRL_AUTHSTATE_NONE;
929
930 break;
931 case OTRL_AUTHSTATE_NONE:
932 case OTRL_AUTHSTATE_AWAITING_DHKEY:
933 case OTRL_AUTHSTATE_AWAITING_SIG:
934 case OTRL_AUTHSTATE_V1_SETUP:
935 /* Ignore this message */
936 *havemsgp = 0;
937 free(buf);
938 buf = NULL;
939 break;
940 }
941
942 return err;
943
944decfail:
945 err = gcry_error(GPG_ERR_NO_ERROR);
946 goto err;
947invval:
948 err = gcry_error(GPG_ERR_INV_VALUE);
949 goto err;
950memerr:
951 err = gcry_error(GPG_ERR_ENOMEM);
952err:
953 free(buf);
954 free(gxbuf);
955 gcry_cipher_close(enc);
956 gcry_mpi_release(incoming_pub);
957 return err;
958}
959
960/*
961 * Handle an incoming Signature Message. If no error is returned, and
962 * *havemsgp is 1, the message to be sent will be left in
963 * auth->lastauthmsg. Call the auth_succeeded callback if
964 * authentication is successful.
965 */
966gcry_error_t otrl_auth_handle_signature(OtrlAuthInfo *auth,
967 const char *sigmsg, int *havemsgp,
968 gcry_error_t (*auth_succeeded)(const OtrlAuthInfo *auth, void *asdata),
969 void *asdata)
970{
971 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
972 unsigned char *buf = NULL, *bufp = NULL;
973 unsigned char *authstart, *authend, *macstart;
974 size_t buflen, lenp, authlen;
975 int res;
976
977 *havemsgp = 0;
978
979 res = otrl_base64_otr_decode(sigmsg, &buf, &buflen);
980 if (res == -1) goto memerr;
981 if (res == -2) goto invval;
982
983 bufp = buf;
984 lenp = buflen;
985
986 /* Header */
987 if (memcmp(bufp, "\x00\x02\x12", 3)) goto invval;
988 bufp += 3; lenp -= 3;
989
990 /* auth */
991 authstart = bufp;
992 read_int(authlen);
993 require_len(authlen);
994 bufp += authlen; lenp -= authlen;
995 authend = bufp;
996
997 /* MAC */
998 require_len(20);
999 macstart = bufp;
1000 bufp += 20; lenp -= 20;
1001
1002 if (lenp != 0) goto invval;
1003
1004 switch(auth->authstate) {
1005 case OTRL_AUTHSTATE_AWAITING_SIG:
1006 /* Check the MAC */
1007 gcry_md_reset(auth->mac_m2p);
1008 gcry_md_write(auth->mac_m2p, authstart, authend - authstart);
1009 if (memcmp(macstart,
1010 gcry_md_read(auth->mac_m2p, GCRY_MD_SHA256),
1011 20)) goto invval;
1012
1013 /* Check the auth */
1014 err = check_pubkey_auth(auth->their_fingerprint,
1015 &(auth->their_keyid), authstart + 4,
1016 authend - authstart - 4, auth->mac_m1p, auth->enc_cp,
1017 auth->our_dh.pub, auth->their_pub);
1018 if (err) goto err;
1019
1020 authstart = NULL;
1021 authend = NULL;
1022 macstart = NULL;
1023 free(buf);
1024 buf = NULL;
1025
1026 /* No error? Then we've completed our end of the
1027 * authentication. */
1028 auth->protocol_version = 2;
1029 auth->session_id_half = OTRL_SESSIONID_FIRST_HALF_BOLD;
1030 if (auth_succeeded) err = auth_succeeded(auth, asdata);
1031 free(auth->lastauthmsg);
1032 auth->lastauthmsg = NULL;
1033 *havemsgp = 1;
1034 auth->our_keyid = 0;
1035 auth->authstate = OTRL_AUTHSTATE_NONE;
1036
1037 break;
1038 case OTRL_AUTHSTATE_NONE:
1039 case OTRL_AUTHSTATE_AWAITING_DHKEY:
1040 case OTRL_AUTHSTATE_AWAITING_REVEALSIG:
1041 case OTRL_AUTHSTATE_V1_SETUP:
1042 /* Ignore this message */
1043 *havemsgp = 0;
1044 break;
1045 }
1046
1047 return err;
1048
1049invval:
1050 err = gcry_error(GPG_ERR_INV_VALUE);
1051 goto err;
1052memerr:
1053 err = gcry_error(GPG_ERR_ENOMEM);
1054err:
1055 free(buf);
1056 return err;
1057}
1058
1059/* Version 1 routines, for compatibility */
1060
1061/*
1062 * Create a verion 1 Key Exchange Message using the values in the given
1063 * auth, and store it in auth->lastauthmsg. Set the Reply field to the
1064 * given value, and use the given privkey to sign the message.
1065 */
1066static gcry_error_t create_v1_key_exchange_message(OtrlAuthInfo *auth,
1067 unsigned char reply, OtrlPrivKey *privkey)
1068{
1069 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
1070 const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
1071 unsigned char *buf = NULL, *bufp = NULL, *sigbuf = NULL;
1072 size_t lenp, ourpublen, totallen, siglen;
1073 unsigned char hashbuf[20];
1074
1075 if (privkey->pubkey_type != OTRL_PUBKEY_TYPE_DSA) {
1076 return gpg_error(GPG_ERR_INV_VALUE);
1077 }
1078
1079 /* How big is the DH public key? */
1080 gcry_mpi_print(format, NULL, 0, &ourpublen, auth->our_dh.pub);
1081
1082 totallen = 3 + 1 + privkey->pubkey_datalen + 4 + 4 + ourpublen + 40;
1083 buf = malloc(totallen);
1084 if (buf == NULL) goto memerr;
1085
1086 bufp = buf;
1087 lenp = totallen;
1088
1089 memmove(bufp, "\x00\x01\x0a", 3); /* header */
1090 debug_data("Header", bufp, 3);
1091 bufp += 3; lenp -= 3;
1092
1093 bufp[0] = reply;
1094 debug_data("Reply", bufp, 1);
1095 bufp += 1; lenp -= 1;
1096
1097 memmove(bufp, privkey->pubkey_data, privkey->pubkey_datalen);
1098 debug_data("Pubkey", bufp, privkey->pubkey_datalen);
1099 bufp += privkey->pubkey_datalen; lenp -= privkey->pubkey_datalen;
1100
1101 write_int(auth->our_keyid);
1102 debug_int("Keyid", bufp-4);
1103
1104 write_mpi(auth->our_dh.pub, ourpublen, "D-H y");
1105
1106 /* Hash all the data written so far, and sign the hash */
1107 gcry_md_hash_buffer(GCRY_MD_SHA1, hashbuf, buf, bufp - buf);
1108
1109 err = otrl_privkey_sign(&sigbuf, &siglen, privkey, hashbuf, 20);
1110 if (err) goto err;
1111
1112 if (siglen != 40) goto invval;
1113 memmove(bufp, sigbuf, 40);
1114 debug_data("Signature", bufp, 40);
1115 bufp += 40; lenp -= 40;
1116 free(sigbuf);
1117 sigbuf = NULL;
1118
1119 assert(lenp == 0);
1120
1121 free(auth->lastauthmsg);
1122 auth->lastauthmsg = otrl_base64_otr_encode(buf, totallen);
1123 if (auth->lastauthmsg == NULL) goto memerr;
1124 free(buf);
1125 buf = NULL;
1126
1127 return err;
1128
1129invval:
1130 err = gcry_error(GPG_ERR_INV_VALUE);
1131 goto err;
1132memerr:
1133 err = gcry_error(GPG_ERR_ENOMEM);
1134err:
1135 free(buf);
1136 free(sigbuf);
1137 return err;
1138}
1139
1140/*
1141 * Start a fresh AKE (version 1) using the given OtrlAuthInfo. If
1142 * our_dh is NULL, generate a fresh DH keypair to use. Otherwise, use a
1143 * copy of the one passed (with the given keyid). Use the given private
1144 * key to sign the message. If no error is returned, the message to
1145 * transmit will be contained in auth->lastauthmsg.
1146 */
1147gcry_error_t otrl_auth_start_v1(OtrlAuthInfo *auth, DH_keypair *our_dh,
1148 unsigned int our_keyid, OtrlPrivKey *privkey)
1149{
1150 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
1151
1152 /* Clear out this OtrlAuthInfo and start over */
1153 otrl_auth_clear(auth);
1154 auth->initiated = 1;
1155
1156 /* Import the given DH keypair, or else create a fresh one */
1157 if (our_dh) {
1158 otrl_dh_keypair_copy(&(auth->our_dh), our_dh);
1159 auth->our_keyid = our_keyid;
1160 } else {
1161 otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
1162 auth->our_keyid = 1;
1163 }
1164
1165 err = create_v1_key_exchange_message(auth, 0, privkey);
1166 if (!err) {
1167 auth->authstate = OTRL_AUTHSTATE_V1_SETUP;
1168 }
1169
1170 return err;
1171}
1172
1173/*
1174 * Handle an incoming v1 Key Exchange Message. If no error is returned,
1175 * and *havemsgp is 1, the message to be sent will be left in
1176 * auth->lastauthmsg. Use the given private authentication key to sign
1177 * messages. Call the auth_secceeded callback if authentication is
1178 * successful. If non-NULL, use a copy of the given D-H keypair, with
1179 * the given keyid.
1180 */
1181gcry_error_t otrl_auth_handle_v1_key_exchange(OtrlAuthInfo *auth,
1182 const char *keyexchmsg, int *havemsgp, OtrlPrivKey *privkey,
1183 DH_keypair *our_dh, unsigned int our_keyid,
1184 gcry_error_t (*auth_succeeded)(const OtrlAuthInfo *auth, void *asdata),
1185 void *asdata)
1186{
1187 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
1188 unsigned char *buf = NULL, *bufp = NULL;
1189 unsigned char *fingerprintstart, *fingerprintend;
1190 unsigned char fingerprintbuf[20], hashbuf[20];
1191 gcry_mpi_t p, q, g, y, received_pub = NULL;
1192 gcry_sexp_t pubs = NULL;
1193 size_t buflen, lenp;
1194 unsigned char received_reply;
1195 unsigned int received_keyid;
1196 int res;
1197
1198 *havemsgp = 0;
1199
1200 res = otrl_base64_otr_decode(keyexchmsg, &buf, &buflen);
1201 if (res == -1) goto memerr;
1202 if (res == -2) goto invval;
1203
1204 bufp = buf;
1205 lenp = buflen;
1206
1207 /* Header */
1208 require_len(3);
1209 if (memcmp(bufp, "\x00\x01\x0a", 3)) goto invval;
1210 bufp += 3; lenp -= 3;
1211
1212 /* Reply */
1213 require_len(1);
1214 received_reply = bufp[0];
1215 bufp += 1; lenp -= 1;
1216
1217 /* Public Key */
1218 fingerprintstart = bufp;
1219 read_mpi(p);
1220 read_mpi(q);
1221 read_mpi(g);
1222 read_mpi(y);
1223 fingerprintend = bufp;
1224 gcry_md_hash_buffer(GCRY_MD_SHA1, fingerprintbuf,
1225 fingerprintstart, fingerprintend-fingerprintstart);
1226 gcry_sexp_build(&pubs, NULL,
1227 "(public-key (dsa (p %m)(q %m)(g %m)(y %m)))", p, q, g, y);
1228 gcry_mpi_release(p);
1229 gcry_mpi_release(q);
1230 gcry_mpi_release(g);
1231 gcry_mpi_release(y);
1232
1233 /* keyid */
1234 read_int(received_keyid);
1235 if (received_keyid == 0) goto invval;
1236
1237 /* D-H pubkey */
1238 read_mpi(received_pub);
1239
1240 /* Verify the signature */
1241 if (lenp != 40) goto invval;
1242 gcry_md_hash_buffer(GCRY_MD_SHA1, hashbuf, buf, bufp - buf);
1243 err = otrl_privkey_verify(bufp, lenp, OTRL_PUBKEY_TYPE_DSA,
1244 pubs, hashbuf, 20);
1245 if (err) goto err;
1246 gcry_sexp_release(pubs);
1247 pubs = NULL;
1248 free(buf);
1249 buf = NULL;
1250
1251 if (auth->authstate != OTRL_AUTHSTATE_V1_SETUP && received_reply == 0x01) {
1252 /* They're replying to something we never sent. We must be
1253 * logged in more than once; ignore the message. */
1254 err = gpg_error(GPG_ERR_NO_ERROR);
1255 goto err;
1256 }
1257
1258 if (auth->authstate != OTRL_AUTHSTATE_V1_SETUP) {
1259 /* Clear the auth and start over */
1260 otrl_auth_clear(auth);
1261 }
1262
1263 /* Everything checked out */
1264 auth->their_keyid = received_keyid;
1265 gcry_mpi_release(auth->their_pub);
1266 auth->their_pub = received_pub;
1267 received_pub = NULL;
1268 memmove(auth->their_fingerprint, fingerprintbuf, 20);
1269
1270 if (received_reply == 0x01) {
1271 /* Don't send a reply to this. */
1272 *havemsgp = 0;
1273 } else {
1274 /* Import the given DH keypair, or else create a fresh one */
1275 if (our_dh) {
1276 otrl_dh_keypair_copy(&(auth->our_dh), our_dh);
1277 auth->our_keyid = our_keyid;
1278 } else if (auth->our_keyid == 0) {
1279 otrl_dh_gen_keypair(DH1536_GROUP_ID, &(auth->our_dh));
1280 auth->our_keyid = 1;
1281 }
1282
1283 /* Reply with our own Key Exchange Message */
1284 err = create_v1_key_exchange_message(auth, 1, privkey);
1285 if (err) goto err;
1286 *havemsgp = 1;
1287 }
1288
1289 /* Compute the session id */
1290 err = otrl_dh_compute_v1_session_id(&(auth->our_dh),
1291 auth->their_pub, auth->secure_session_id,
1292 &(auth->secure_session_id_len),
1293 &(auth->session_id_half));
1294 if (err) goto err;
1295
1296 /* We've completed our end of the authentication */
1297 auth->protocol_version = 1;
1298 if (auth_succeeded) err = auth_succeeded(auth, asdata);
1299 auth->our_keyid = 0;
1300 auth->authstate = OTRL_AUTHSTATE_NONE;
1301
1302 return err;
1303
1304invval:
1305 err = gcry_error(GPG_ERR_INV_VALUE);
1306 goto err;
1307memerr:
1308 err = gcry_error(GPG_ERR_ENOMEM);
1309err:
1310 free(buf);
1311 gcry_sexp_release(pubs);
1312 gcry_mpi_release(received_pub);
1313 return err;
1314}
1315
1316#ifdef OTRL_TESTING_AUTH
1317#include "mem.h"
1318#include "privkey.h"
1319
1320#define CHECK_ERR if (err) { printf("Error: %s\n", gcry_strerror(err)); return 1; }
1321
1322static gcry_error_t starting(const OtrlAuthInfo *auth, void *asdata)
1323{
1324 char *name = asdata;
1325
1326 fprintf(stderr, "\nStarting ENCRYPTED mode for %s (v%d).\n", name, auth->protocol_version);
1327
1328 fprintf(stderr, "\nour_dh (%d):", auth->our_keyid);
1329 gcry_mpi_dump(auth->our_dh.pub);
1330 fprintf(stderr, "\ntheir_pub (%d):", auth->their_keyid);
1331 gcry_mpi_dump(auth->their_pub);
1332
1333 debug_data("\nTheir fingerprint", auth->their_fingerprint, 20);
1334 debug_data("\nSecure session id", auth->secure_session_id,
1335 auth->secure_session_id_len);
1336 fprintf(stderr, "Sessionid half: %d\n\n", auth->session_id_half);
1337
1338 return gpg_error(GPG_ERR_NO_ERROR);
1339}
1340
1341int main(int argc, char **argv)
1342{
1343 OtrlAuthInfo alice, bob;
1344 gcry_error_t err;
1345 int havemsg;
1346 OtrlUserState us;
1347 OtrlPrivKey *alicepriv, *bobpriv;
1348
1349 otrl_mem_init();
1350 otrl_dh_init();
1351 otrl_auth_new(&alice);
1352 otrl_auth_new(&bob);
1353
1354 us = otrl_userstate_create();
1355 otrl_privkey_read(us, "/home/iang/.gaim/otr.private_key");
1356 alicepriv = otrl_privkey_find(us, "oneeyedian", "prpl-oscar");
1357 bobpriv = otrl_privkey_find(us, "otr4ian", "prpl-oscar");
1358
1359 printf("\n\n ***** V2 *****\n\n");
1360
1361 err = otrl_auth_start_v2(&bob, NULL, 0);
1362 CHECK_ERR
1363 printf("\nBob: %d\n%s\n\n", strlen(bob.lastauthmsg), bob.lastauthmsg);
1364 err = otrl_auth_handle_commit(&alice, bob.lastauthmsg, NULL, 0);
1365 CHECK_ERR
1366 printf("\nAlice: %d\n%s\n\n", strlen(alice.lastauthmsg), alice.lastauthmsg);
1367 err = otrl_auth_handle_key(&bob, alice.lastauthmsg, &havemsg, bobpriv);
1368 CHECK_ERR
1369 if (havemsg) {
1370 printf("\nBob: %d\n%s\n\n", strlen(bob.lastauthmsg), bob.lastauthmsg);
1371 } else {
1372 printf("\nIGNORE\n\n");
1373 }
1374 err = otrl_auth_handle_revealsig(&alice, bob.lastauthmsg, &havemsg,
1375 alicepriv, starting, "Alice");
1376 CHECK_ERR
1377 if (havemsg) {
1378 printf("\nAlice: %d\n%s\n\n", strlen(alice.lastauthmsg), alice.lastauthmsg);
1379 } else {
1380 printf("\nIGNORE\n\n");
1381 }
1382 err = otrl_auth_handle_signature(&bob, alice.lastauthmsg, &havemsg,
1383 starting, "Bob");
1384 CHECK_ERR
1385
1386 printf("\n\n ***** V1 *****\n\n");
1387
1388 err = otrl_auth_start_v1(&bob, NULL, 0, bobpriv);
1389 CHECK_ERR
1390 printf("\nBob: %d\n%s\n\n", strlen(bob.lastauthmsg), bob.lastauthmsg);
1391 err = otrl_auth_handle_v1_key_exchange(&alice, bob.lastauthmsg,
1392 &havemsg, alicepriv, NULL, 0, starting, "Alice");
1393 CHECK_ERR
1394 if (havemsg) {
1395 printf("\nAlice: %d\n%s\n\n", strlen(alice.lastauthmsg), alice.lastauthmsg);
1396 } else {
1397 printf("\nIGNORE\n\n");
1398 }
1399 err = otrl_auth_handle_v1_key_exchange(&bob, alice.lastauthmsg,
1400 &havemsg, bobpriv, NULL, 0, starting, "Bob");
1401 CHECK_ERR
1402 if (havemsg) {
1403 printf("\nBob: %d\n%s\n\n", strlen(bob.lastauthmsg), bob.lastauthmsg);
1404 } else {
1405 printf("\nIGNORE\n\n");
1406 }
1407
1408 otrl_userstate_free(us);
1409 otrl_auth_clear(&alice);
1410 otrl_auth_clear(&bob);
1411 return 0;
1412}
1413#endif
diff --git a/linden/indra/libotr/libotr-3.2.0/src/auth.h b/linden/indra/libotr/libotr-3.2.0/src/auth.h
new file mode 100755
index 0000000..6de75dd
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/auth.h
@@ -0,0 +1,157 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef __AUTH_H__
21#define __AUTH_H__
22
23#include <gcrypt.h>
24#include "dh.h"
25
26typedef enum {
27 OTRL_AUTHSTATE_NONE,
28 OTRL_AUTHSTATE_AWAITING_DHKEY,
29 OTRL_AUTHSTATE_AWAITING_REVEALSIG,
30 OTRL_AUTHSTATE_AWAITING_SIG,
31 OTRL_AUTHSTATE_V1_SETUP
32} OtrlAuthState;
33
34typedef struct {
35 OtrlAuthState authstate; /* Our state */
36
37 DH_keypair our_dh; /* Our D-H key */
38 unsigned int our_keyid; /* ...and its keyid */
39
40 unsigned char *encgx; /* The encrypted value of g^x */
41 size_t encgx_len; /* ...and its length */
42 unsigned char r[16]; /* The encryption key */
43
44 unsigned char hashgx[32]; /* SHA256(g^x) */
45
46 gcry_mpi_t their_pub; /* Their D-H public key */
47 unsigned int their_keyid; /* ...and its keyid */
48
49 gcry_cipher_hd_t enc_c, enc_cp; /* c and c' encryption keys */
50 gcry_md_hd_t mac_m1, mac_m1p; /* m1 and m1' MAC keys */
51 gcry_md_hd_t mac_m2, mac_m2p; /* m2 and m2' MAC keys */
52
53 unsigned char their_fingerprint[20]; /* The fingerprint of their
54 long-term signing key */
55
56 int initiated; /* Did we initiate this
57 authentication? */
58
59 unsigned int protocol_version; /* The protocol version number
60 used to authenticate. */
61
62 unsigned char secure_session_id[20]; /* The secure session id */
63 size_t secure_session_id_len; /* And its actual length,
64 which may be either 20 (for
65 v1) or 8 (for v2) */
66 OtrlSessionIdHalf session_id_half; /* Which half of the session
67 id gets shown in bold */
68
69 char *lastauthmsg; /* The last auth message
70 (base-64 encoded) we sent,
71 in case we need to
72 retransmit it. */
73} OtrlAuthInfo;
74
75#include "privkey-t.h"
76
77/*
78 * Initialize the fields of an OtrlAuthInfo (already allocated).
79 */
80void otrl_auth_new(OtrlAuthInfo *auth);
81
82/*
83 * Clear the fields of an OtrlAuthInfo (but leave it allocated).
84 */
85void otrl_auth_clear(OtrlAuthInfo *auth);
86
87/*
88 * Start a fresh AKE (version 2) using the given OtrlAuthInfo. Generate
89 * a fresh DH keypair to use. If no error is returned, the message to
90 * transmit will be contained in auth->lastauthmsg.
91 */
92gcry_error_t otrl_auth_start_v2(OtrlAuthInfo *auth);
93
94/*
95 * Handle an incoming D-H Commit Message. If no error is returned, the
96 * message to send will be left in auth->lastauthmsg. Generate a fresh
97 * keypair to use.
98 */
99gcry_error_t otrl_auth_handle_commit(OtrlAuthInfo *auth,
100 const char *commitmsg);
101
102/*
103 * Handle an incoming D-H Key Message. If no error is returned, and
104 * *havemsgp is 1, the message to sent will be left in auth->lastauthmsg.
105 * Use the given private authentication key to sign messages.
106 */
107gcry_error_t otrl_auth_handle_key(OtrlAuthInfo *auth, const char *keymsg,
108 int *havemsgp, OtrlPrivKey *privkey);
109
110/*
111 * Handle an incoming Reveal Signature Message. If no error is
112 * returned, and *havemsgp is 1, the message to be sent will be left in
113 * auth->lastauthmsg. Use the given private authentication key to sign
114 * messages. Call the auth_succeeded callback if authentication is
115 * successful.
116 */
117gcry_error_t otrl_auth_handle_revealsig(OtrlAuthInfo *auth,
118 const char *revealmsg, int *havemsgp, OtrlPrivKey *privkey,
119 gcry_error_t (*auth_succeeded)(const OtrlAuthInfo *auth, void *asdata),
120 void *asdata);
121
122/*
123 * Handle an incoming Signature Message. If no error is returned, and
124 * *havemsgp is 1, the message to be sent will be left in
125 * auth->lastauthmsg. Call the auth_succeeded callback if
126 * authentication is successful.
127 */
128gcry_error_t otrl_auth_handle_signature(OtrlAuthInfo *auth,
129 const char *sigmsg, int *havemsgp,
130 gcry_error_t (*auth_succeeded)(const OtrlAuthInfo *auth, void *asdata),
131 void *asdata);
132
133/*
134 * Start a fresh AKE (version 1) using the given OtrlAuthInfo. If
135 * our_dh is NULL, generate a fresh DH keypair to use. Otherwise, use a
136 * copy of the one passed (with the given keyid). Use the given private
137 * key to sign the message. If no error is returned, the message to
138 * transmit will be contained in auth->lastauthmsg.
139 */
140gcry_error_t otrl_auth_start_v1(OtrlAuthInfo *auth, DH_keypair *our_dh,
141 unsigned int our_keyid, OtrlPrivKey *privkey);
142
143/*
144 * Handle an incoming v1 Key Exchange Message. If no error is returned,
145 * and *havemsgp is 1, the message to be sent will be left in
146 * auth->lastauthmsg. Use the given private authentication key to sign
147 * messages. Call the auth_secceeded callback if authentication is
148 * successful. If non-NULL, use a copy of the given D-H keypair, with
149 * the given keyid.
150 */
151gcry_error_t otrl_auth_handle_v1_key_exchange(OtrlAuthInfo *auth,
152 const char *keyexchmsg, int *havemsgp, OtrlPrivKey *privkey,
153 DH_keypair *our_dh, unsigned int our_keyid,
154 gcry_error_t (*auth_succeeded)(const OtrlAuthInfo *auth, void *asdata),
155 void *asdata);
156
157#endif
diff --git a/linden/indra/libotr/libotr-3.2.0/src/b64.c b/linden/indra/libotr/libotr-3.2.0/src/b64.c
new file mode 100755
index 0000000..b8736da
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/b64.c
@@ -0,0 +1,249 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/* Modified from: */
21
22/*********************************************************************\
23
24MODULE NAME: b64.c
25
26AUTHOR: Bob Trower 08/04/01
27
28LICENCE: Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc.
29
30 Permission is hereby granted, free of charge, to any person
31 obtaining a copy of this software and associated
32 documentation files (the "Software"), to deal in the
33 Software without restriction, including without limitation
34 the rights to use, copy, modify, merge, publish, distribute,
35 sublicense, and/or sell copies of the Software, and to
36 permit persons to whom the Software is furnished to do so,
37 subject to the following conditions:
38
39 The above copyright notice and this permission notice shall
40 be included in all copies or substantial portions of the
41 Software.
42
43 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
44 KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
45 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
46 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
47 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
48 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
49 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
50 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
51
52VERSION HISTORY:
53 Bob Trower 08/04/01 -- Create Version 0.00.00B
54
55\******************************************************************* */
56
57/* system headers */
58#include <stdlib.h>
59#include <string.h>
60
61/* libotr headers */
62#include "b64.h"
63
64/*
65** Translation Table as described in RFC1113
66*/
67static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
68
69/*
70** Translation Table to decode (created by author)
71*/
72static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
73
74/*
75** encodeblock
76**
77** encode up to 3 8-bit binary bytes as 4 '6-bit' characters.
78** len must be 1, 2, or 3.
79*/
80static void encodeblock( char *out, const unsigned char *in, size_t len )
81{
82 unsigned char in0, in1, in2;
83 in0 = in[0];
84 in1 = len > 1 ? in[1] : 0;
85 in2 = len > 2 ? in[2] : 0;
86
87 out[0] = cb64[ in0 >> 2 ];
88 out[1] = cb64[ ((in0 & 0x03) << 4) | ((in1 & 0xf0) >> 4) ];
89 out[2] = len > 1 ? cb64[ ((in1 & 0x0f) << 2) | ((in2 & 0xc0) >> 6) ]
90 : '=';
91 out[3] = len > 2 ? cb64[ in2 & 0x3f ]
92 : '=';
93}
94
95/*
96 * base64 encode data. Insert no linebreaks or whitespace.
97 *
98 * The buffer base64data must contain at least ((datalen+2)/3)*4 bytes of
99 * space. This function will return the number of bytes actually used.
100 */
101size_t otrl_base64_encode(char *base64data, const unsigned char *data,
102 size_t datalen)
103{
104 size_t base64len = 0;
105
106 while(datalen > 2) {
107 encodeblock(base64data, data, 3);
108 base64data += 4;
109 base64len += 4;
110 data += 3;
111 datalen -= 3;
112 }
113 if (datalen > 0) {
114 encodeblock(base64data, data, datalen);
115 base64len += 4;
116 }
117
118 return base64len;
119}
120
121static size_t decode(unsigned char *out, const char *in, size_t b64len)
122{
123 size_t written = 0;
124 unsigned char c = 0;
125
126 if (b64len > 0) {
127 c = in[0] << 2;
128 }
129 if (b64len > 1) {
130 out[0] = c | in[1] >> 4;
131 written = 1;
132 c = in[1] << 4;
133 }
134 if (b64len > 2) {
135 out[1] = c | in[2] >> 2;
136 written = 2;
137 c = in[2] << 6;
138 }
139 if (b64len > 3) {
140 out[2] = c | in[3];
141 written = 3;
142 }
143 return written;
144}
145
146/*
147 * base64 decode data. Skip non-base64 chars, and terminate at the
148 * first '=', or the end of the buffer.
149 *
150 * The buffer data must contain at least (base64len / 4) * 3 bytes of
151 * space. This function will return the number of bytes actually used.
152 */
153size_t otrl_base64_decode(unsigned char *data, const char *base64data,
154 size_t base64len)
155{
156 size_t datalen = 0;
157 char b64[4];
158 size_t b64accum = 0;
159
160 while(base64len > 0) {
161 char b = *base64data;
162 unsigned char bdecode;
163 ++base64data;
164 --base64len;
165 if (b < '+' || b > 'z') continue; /* Skip non-base64 chars */
166 if (b == '=') {
167 /* Force termination */
168 datalen += decode(data, b64, b64accum);
169 base64len = 0;
170 } else {
171 bdecode = cd64[b-'+'];
172 if (bdecode == '$') continue; /* Skip non-base64 chars */
173 b64[b64accum++] = bdecode-'>';
174 if (b64accum == 4) {
175 /* We have a complete block; decode it. */
176 size_t written = decode(data, b64, b64accum);
177 data += written;
178 datalen += written;
179 b64accum = 0;
180 }
181 }
182 }
183
184 /* Just discard any short block at the end. */
185
186 return datalen;
187}
188
189/*
190 * Base64-encode a block of data, stick "?OTR:" and "." around it, and
191 * return the result, or NULL in the event of a memory error. The
192 * caller must free() the return value.
193 */
194char *otrl_base64_otr_encode(const unsigned char *buf, size_t buflen)
195{
196 char *base64buf;
197 size_t base64len;
198
199 /* Make the base64-encoding. */
200 base64len = ((buflen + 2) / 3) * 4;
201 base64buf = malloc(5 + base64len + 1 + 1);
202 if (base64buf == NULL) {
203 return NULL;
204 }
205 memmove(base64buf, "?OTR:", 5);
206 otrl_base64_encode(base64buf+5, buf, buflen);
207 base64buf[5 + base64len] = '.';
208 base64buf[5 + base64len + 1] = '\0';
209
210 return base64buf;
211}
212
213/*
214 * Base64-decode the portion of the given message between "?OTR:" and
215 * ".". Set *bufp to the decoded data, and set *lenp to its length.
216 * The caller must free() the result. Return 0 on success, -1 on a
217 * memory error, or -2 on invalid input.
218 */
219int otrl_base64_otr_decode(const char *msg, unsigned char **bufp,
220 size_t *lenp)
221{
222 char *otrtag, *endtag;
223 size_t msglen, rawlen;
224 unsigned char *rawmsg;
225
226 otrtag = strstr(msg, "?OTR:");
227 if (!otrtag) {
228 return -2;
229 }
230 endtag = strchr(otrtag, '.');
231 if (endtag) {
232 msglen = endtag-otrtag;
233 } else {
234 return -2;
235 }
236
237 /* Base64-decode the message */
238 rawlen = ((msglen-5) / 4) * 3; /* maximum possible */
239 rawmsg = malloc(rawlen);
240 if (!rawmsg && rawlen > 0) {
241 return -1;
242 }
243 rawlen = otrl_base64_decode(rawmsg, otrtag+5, msglen-5); /* actual size */
244
245 *bufp = rawmsg;
246 *lenp = rawlen;
247
248 return 0;
249}
diff --git a/linden/indra/libotr/libotr-3.2.0/src/b64.h b/linden/indra/libotr/libotr-3.2.0/src/b64.h
new file mode 100755
index 0000000..34ef03f
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/b64.h
@@ -0,0 +1,57 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef __B64_H__
21#define __B64_H__
22
23/*
24 * base64 encode data. Insert no linebreaks or whitespace.
25 *
26 * The buffer base64data must contain at least ((datalen+2)/3)*4 bytes of
27 * space. This function will return the number of bytes actually used.
28 */
29size_t otrl_base64_encode(char *base64data, const unsigned char *data,
30 size_t datalen);
31
32/*
33 * base64 decode data. Skip non-base64 chars, and terminate at the
34 * first '=', or the end of the buffer.
35 *
36 * The buffer data must contain at least (base64len / 4) * 3 bytes of
37 * space. This function will return the number of bytes actually used.
38 */
39size_t otrl_base64_decode(unsigned char *data, const char *base64data,
40 size_t base64len);
41
42/*
43 * Base64-encode a block of data, stick "?OTR:" and "." around it, and
44 * return the result, or NULL in the event of a memory error.
45 */
46char *otrl_base64_otr_encode(const unsigned char *buf, size_t buflen);
47
48/*
49 * Base64-decode the portion of the given message between "?OTR:" and
50 * ".". Set *bufp to the decoded data, and set *lenp to its length.
51 * The caller must free() the result. Return 0 on success, -1 on a
52 * memory error, or -2 on invalid input.
53 */
54int otrl_base64_otr_decode(const char *msg, unsigned char **bufp,
55 size_t *lenp);
56
57#endif
diff --git a/linden/indra/libotr/libotr-3.2.0/src/context.c b/linden/indra/libotr/libotr-3.2.0/src/context.c
new file mode 100755
index 0000000..4b2369a
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/context.c
@@ -0,0 +1,321 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/* system headers */
21#include <stdlib.h>
22#include <assert.h>
23
24/* libgcrypt headers */
25#include <gcrypt.h>
26
27/* libotr headers */
28#include "context.h"
29#include "proto.h"
30
31/* Create a new connection context. */
32static ConnContext * new_context(const char * user, const char * accountname,
33 const char * protocol)
34{
35 ConnContext * context;
36 OtrlSMState *smstate;
37 context = malloc(sizeof(*context));
38 assert(context != NULL);
39 context->username = strdup(user);
40 context->accountname = strdup(accountname);
41 context->protocol = strdup(protocol);
42 context->fragments = NULL;
43 context->fragment_len = 0;
44 context->fragment_n = 0;
45 context->fragment_k = 0;
46 context->msgstate = OTRL_MSGSTATE_PLAINTEXT;
47 otrl_auth_new(&(context->auth));
48
49 smstate = malloc(sizeof(OtrlSMState));
50 assert(smstate != NULL);
51 otrl_sm_state_new(smstate);
52 context->smstate = smstate;
53
54 context->fingerprint_root.fingerprint = NULL;
55 context->fingerprint_root.context = context;
56 context->fingerprint_root.next = NULL;
57 context->fingerprint_root.tous = NULL;
58 context->active_fingerprint = NULL;
59 context->their_keyid = 0;
60 context->their_y = NULL;
61 context->their_old_y = NULL;
62 context->our_keyid = 0;
63 context->our_dh_key.groupid = 0;
64 context->our_dh_key.priv = NULL;
65 context->our_dh_key.pub = NULL;
66 context->our_old_dh_key.groupid = 0;
67 context->our_old_dh_key.priv = NULL;
68 context->our_old_dh_key.pub = NULL;
69 otrl_dh_session_blank(&(context->sesskeys[0][0]));
70 otrl_dh_session_blank(&(context->sesskeys[0][1]));
71 otrl_dh_session_blank(&(context->sesskeys[1][0]));
72 otrl_dh_session_blank(&(context->sesskeys[1][1]));
73 memset(context->sessionid, 0, 20);
74 context->sessionid_len = 0;
75 context->protocol_version = 0;
76 context->numsavedkeys = 0;
77 context->preshared_secret = NULL;
78 context->preshared_secret_len = 0;
79 context->saved_mac_keys = NULL;
80 context->generation = 0;
81 context->lastsent = 0;
82 context->lastmessage = NULL;
83 context->may_retransmit = 0;
84 context->otr_offer = OFFER_NOT;
85 context->app_data = NULL;
86 context->app_data_free = NULL;
87 context->next = NULL;
88 return context;
89}
90
91/* Look up a connection context by name/account/protocol from the given
92 * OtrlUserState. If add_if_missing is true, allocate and return a new
93 * context if one does not currently exist. In that event, call
94 * add_app_data(data, context) so that app_data and app_data_free can be
95 * filled in by the application, and set *addedp to 1. */
96ConnContext * otrl_context_find(OtrlUserState us, const char *user,
97 const char *accountname, const char *protocol, int add_if_missing,
98 int *addedp,
99 void (*add_app_data)(void *data, ConnContext *context), void *data)
100{
101 ConnContext ** curp;
102 int usercmp = 1, acctcmp = 1, protocmp = 1;
103 if (addedp) *addedp = 0;
104 if (!user || !accountname || !protocol) return NULL;
105 for (curp = &(us->context_root); *curp; curp = &((*curp)->next)) {
106 if ((usercmp = strcmp((*curp)->username, user)) > 0 ||
107 (usercmp == 0 &&
108 (acctcmp = strcmp((*curp)->accountname, accountname)) > 0) ||
109 (usercmp == 0 && acctcmp == 0 &&
110 (protocmp = strcmp((*curp)->protocol, protocol)) >= 0))
111 /* We're at the right place in the list. We've either found
112 * it, or gone too far. */
113 break;
114 }
115 if (usercmp == 0 && acctcmp == 0 && protocmp == 0) {
116 /* Found it! */
117 return *curp;
118 }
119 if (add_if_missing) {
120 ConnContext *newctx;
121 if (addedp) *addedp = 1;
122 newctx = new_context(user, accountname, protocol);
123 newctx->next = *curp;
124 if (*curp) {
125 (*curp)->tous = &(newctx->next);
126 }
127 *curp = newctx;
128 newctx->tous = curp;
129 if (add_app_data) {
130 add_app_data(data, *curp);
131 }
132 return *curp;
133 }
134 return NULL;
135}
136
137/* Find a fingerprint in a given context, perhaps adding it if not
138 * present. */
139Fingerprint *otrl_context_find_fingerprint(ConnContext *context,
140 unsigned char fingerprint[20], int add_if_missing, int *addedp)
141{
142 Fingerprint *f = context->fingerprint_root.next;
143 if (addedp) *addedp = 0;
144 while(f) {
145 if (!memcmp(f->fingerprint, fingerprint, 20)) return f;
146 f = f->next;
147 }
148 /* Didn't find it. */
149 if (add_if_missing) {
150 if (addedp) *addedp = 1;
151 f = malloc(sizeof(*f));
152 assert(f != NULL);
153 f->fingerprint = malloc(20);
154 assert(f->fingerprint != NULL);
155 memmove(f->fingerprint, fingerprint, 20);
156 f->context = context;
157 f->trust = NULL;
158 f->next = context->fingerprint_root.next;
159 if (f->next) {
160 f->next->tous = &(f->next);
161 }
162 context->fingerprint_root.next = f;
163 f->tous = &(context->fingerprint_root.next);
164 return f;
165 }
166 return NULL;
167}
168
169/* Set the trust level for a given fingerprint */
170void otrl_context_set_trust(Fingerprint *fprint, const char *trust)
171{
172 if (fprint == NULL) return;
173
174 free(fprint->trust);
175 fprint->trust = trust ? strdup(trust) : NULL;
176}
177
178/* Set the preshared secret for a given fingerprint. Note that this
179 * currently only stores the secret in the ConnContext structure, but
180 * doesn't yet do anything with it. */
181void otrl_context_set_preshared_secret(ConnContext *context,
182 const unsigned char *secret, size_t secret_len)
183{
184 free(context->preshared_secret);
185 context->preshared_secret = NULL;
186 context->preshared_secret_len = 0;
187
188 if (secret_len) {
189 context->preshared_secret = malloc(secret_len);
190 if (context->preshared_secret) {
191 memmove(context->preshared_secret, secret, secret_len);
192 context->preshared_secret_len = secret_len;
193 }
194 }
195}
196
197/* Force a context into the OTRL_MSGSTATE_FINISHED state. */
198void otrl_context_force_finished(ConnContext *context)
199{
200 context->msgstate = OTRL_MSGSTATE_FINISHED;
201 otrl_auth_clear(&(context->auth));
202 otrl_free_fragments(context);
203 context->active_fingerprint = NULL;
204 context->their_keyid = 0;
205 gcry_mpi_release(context->their_y);
206 context->their_y = NULL;
207 gcry_mpi_release(context->their_old_y);
208 context->their_old_y = NULL;
209 context->our_keyid = 0;
210 otrl_dh_keypair_free(&(context->our_dh_key));
211 otrl_dh_keypair_free(&(context->our_old_dh_key));
212 otrl_dh_session_free(&(context->sesskeys[0][0]));
213 otrl_dh_session_free(&(context->sesskeys[0][1]));
214 otrl_dh_session_free(&(context->sesskeys[1][0]));
215 otrl_dh_session_free(&(context->sesskeys[1][1]));
216 memset(context->sessionid, 0, 20);
217 context->sessionid_len = 0;
218 free(context->preshared_secret);
219 context->preshared_secret = NULL;
220 context->preshared_secret_len = 0;
221 context->protocol_version = 0;
222 context->numsavedkeys = 0;
223 free(context->saved_mac_keys);
224 context->saved_mac_keys = NULL;
225 gcry_free(context->lastmessage);
226 context->lastmessage = NULL;
227 context->may_retransmit = 0;
228 otrl_sm_state_free(context->smstate);
229}
230
231/* Force a context into the OTRL_MSGSTATE_PLAINTEXT state. */
232void otrl_context_force_plaintext(ConnContext *context)
233{
234 /* First clean up everything we'd need to do for the FINISHED state */
235 otrl_context_force_finished(context);
236
237 /* And just set the state properly */
238 context->msgstate = OTRL_MSGSTATE_PLAINTEXT;
239}
240
241/* Forget a fingerprint (so long as it's not the active one. If it's a
242 * fingerprint_root, forget the whole context (as long as
243 * and_maybe_context is set, and it's PLAINTEXT). Also, if it's not
244 * the fingerprint_root, but it's the only fingerprint, and we're
245 * PLAINTEXT, forget the whole context if and_maybe_context is set. */
246void otrl_context_forget_fingerprint(Fingerprint *fprint,
247 int and_maybe_context)
248{
249 ConnContext *context = fprint->context;
250 if (fprint == &(context->fingerprint_root)) {
251 if (context->msgstate == OTRL_MSGSTATE_PLAINTEXT &&
252 and_maybe_context) {
253 otrl_context_forget(context);
254 }
255 } else {
256 if (context->msgstate != OTRL_MSGSTATE_PLAINTEXT ||
257 context->active_fingerprint != fprint) {
258 free(fprint->fingerprint);
259 free(fprint->trust);
260 *(fprint->tous) = fprint->next;
261 if (fprint->next) {
262 fprint->next->tous = fprint->tous;
263 }
264 free(fprint);
265 if (context->msgstate == OTRL_MSGSTATE_PLAINTEXT &&
266 context->fingerprint_root.next == NULL &&
267 and_maybe_context) {
268 /* We just deleted the only fingerprint. Forget the
269 * whole thing. */
270 otrl_context_forget(context);
271 }
272 }
273 }
274}
275
276/* Forget a whole context, so long as it's PLAINTEXT. */
277void otrl_context_forget(ConnContext *context)
278{
279 if (context->msgstate != OTRL_MSGSTATE_PLAINTEXT) return;
280
281 /* Just to be safe, force to plaintext. This also frees any
282 * extraneous data lying around. */
283 otrl_context_force_plaintext(context);
284
285 /* First free all the Fingerprints */
286 while(context->fingerprint_root.next) {
287 otrl_context_forget_fingerprint(context->fingerprint_root.next, 0);
288 }
289 /* Now free all the dynamic info here */
290 free(context->username);
291 free(context->accountname);
292 free(context->protocol);
293 free(context->smstate);
294 context->username = NULL;
295 context->accountname = NULL;
296 context->protocol = NULL;
297 context->smstate = NULL;
298
299 /* Free the application data, if it exists */
300 if (context->app_data && context->app_data_free) {
301 (context->app_data_free)(context->app_data);
302 context->app_data = NULL;
303 }
304
305 /* Fix the list linkages */
306 *(context->tous) = context->next;
307 if (context->next) {
308 context->next->tous = context->tous;
309 }
310
311 free(context);
312}
313
314/* Forget all the contexts in a given OtrlUserState. */
315void otrl_context_forget_all(OtrlUserState us)
316{
317 while (us->context_root) {
318 otrl_context_force_plaintext(us->context_root);
319 otrl_context_forget(us->context_root);
320 }
321}
diff --git a/linden/indra/libotr/libotr-3.2.0/src/context.h b/linden/indra/libotr/libotr-3.2.0/src/context.h
new file mode 100755
index 0000000..b68bd8d
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/context.h
@@ -0,0 +1,179 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef __CONTEXT_H__
21#define __CONTEXT_H__
22
23#include <gcrypt.h>
24
25#include "dh.h"
26#include "auth.h"
27#include "sm.h"
28
29typedef enum {
30 OTRL_MSGSTATE_PLAINTEXT, /* Not yet started an encrypted
31 conversation */
32 OTRL_MSGSTATE_ENCRYPTED, /* Currently in an encrypted
33 conversation */
34 OTRL_MSGSTATE_FINISHED /* The remote side has sent us a
35 notification that he has ended
36 his end of the encrypted
37 conversation; prevent any
38 further messages from being
39 sent to him. */
40} OtrlMessageState;
41
42typedef struct s_fingerprint {
43 struct s_fingerprint *next; /* The next fingerprint in the list */
44 struct s_fingerprint **tous; /* A pointer to the pointer to us */
45 unsigned char *fingerprint; /* The fingerprint, or NULL */
46 struct context *context; /* The context to which we belong */
47 char *trust; /* The trust level of the fingerprint */
48} Fingerprint;
49
50typedef struct context {
51 struct context * next; /* Linked list pointer */
52 struct context ** tous; /* A pointer to the pointer to us */
53
54 char * username; /* The user this context is for */
55 char * accountname; /* The username is relative to
56 this account... */
57 char * protocol; /* ... and this protocol */
58
59 char **fragments; /* The parts of the fragmented message
60 we've seen so far */
61 size_t fragment_len; /* The length of fragment */
62 unsigned short fragment_n; /* The total number of fragments
63 in this message */
64 unsigned short fragment_k; /* The highest fragment number
65 we've seen so far for this
66 message */
67
68 OtrlMessageState msgstate; /* The state of message disposition
69 with this user */
70 OtrlAuthInfo auth; /* The state of ongoing
71 authentication with this user */
72
73 Fingerprint fingerprint_root; /* The root of a linked list of
74 Fingerprints entries */
75 Fingerprint *active_fingerprint; /* Which fingerprint is in use now?
76 A pointer into the above list */
77 unsigned int their_keyid; /* current keyid used by other side;
78 this is set to 0 if we get a
79 OTRL_TLV_DISCONNECTED message from
80 them. */
81 gcry_mpi_t their_y; /* Y[their_keyid] (their DH pubkey) */
82 gcry_mpi_t their_old_y; /* Y[their_keyid-1] (their prev DH
83 pubkey) */
84 unsigned int our_keyid; /* current keyid used by us */
85 DH_keypair our_dh_key; /* DH key[our_keyid] */
86 DH_keypair our_old_dh_key; /* DH key[our_keyid-1] */
87
88 DH_sesskeys sesskeys[2][2]; /* sesskeys[i][j] are the session keys
89 derived from DH key[our_keyid-i]
90 and mpi Y[their_keyid-j] */
91
92 unsigned char sessionid[20]; /* The sessionid and bold half */
93 size_t sessionid_len; /* determined when this private */
94 OtrlSessionIdHalf sessionid_half; /* connection was established. */
95
96 unsigned int protocol_version; /* The version of OTR in use */
97
98 unsigned char *preshared_secret; /* A secret you share with this
99 user, in order to do
100 authentication. */
101 size_t preshared_secret_len; /* The length of the above secret. */
102
103 /* saved mac keys to be revealed later */
104 unsigned int numsavedkeys;
105 unsigned char *saved_mac_keys;
106
107 /* generation number: increment every time we go private, and never
108 * reset to 0 (unless we remove the context entirely) */
109 unsigned int generation;
110
111 time_t lastsent; /* The last time a Data Message was sent */
112 char *lastmessage; /* The plaintext of the last Data Message sent */
113 int may_retransmit; /* Is the last message eligible for
114 retransmission? */
115
116 enum {
117 OFFER_NOT,
118 OFFER_SENT,
119 OFFER_REJECTED,
120 OFFER_ACCEPTED
121 } otr_offer; /* Has this correspondent repsponded to our
122 OTR offers? */
123
124 /* Application data to be associated with this context */
125 void *app_data;
126 /* A function to free the above data when we forget this context */
127 void (*app_data_free)(void *);
128
129 OtrlSMState *smstate; /* The state of the current
130 socialist millionaires exchange */
131} ConnContext;
132
133#include "userstate.h"
134
135/* Look up a connection context by name/account/protocol from the given
136 * OtrlUserState. If add_if_missing is true, allocate and return a new
137 * context if one does not currently exist. In that event, call
138 * add_app_data(data, context) so that app_data and app_data_free can be
139 * filled in by the application, and set *addedp to 1. */
140ConnContext * otrl_context_find(OtrlUserState us, const char *user,
141 const char *accountname, const char *protocol, int add_if_missing,
142 int *addedp,
143 void (*add_app_data)(void *data, ConnContext *context), void *data);
144
145/* Find a fingerprint in a given context, perhaps adding it if not
146 * present. */
147Fingerprint *otrl_context_find_fingerprint(ConnContext *context,
148 unsigned char fingerprint[20], int add_if_missing, int *addedp);
149
150/* Set the trust level for a given fingerprint */
151void otrl_context_set_trust(Fingerprint *fprint, const char *trust);
152
153/* Set the preshared secret for a given fingerprint. Note that this
154 * currently only stores the secret in the ConnContext structure, but
155 * doesn't yet do anything with it. */
156void otrl_context_set_preshared_secret(ConnContext *context,
157 const unsigned char *secret, size_t secret_len);
158
159/* Force a context into the OTRL_MSGSTATE_FINISHED state. */
160void otrl_context_force_finished(ConnContext *context);
161
162/* Force a context into the OTRL_MSGSTATE_PLAINTEXT state. */
163void otrl_context_force_plaintext(ConnContext *context);
164
165/* Forget a fingerprint (so long as it's not the active one. If it's a
166 * fingerprint_root, forget the whole context (as long as
167 * and_maybe_context is set, and it's PLAINTEXT). Also, if it's not
168 * the fingerprint_root, but it's the only fingerprint, and we're
169 * PLAINTEXT, forget the whole context if and_maybe_context is set. */
170void otrl_context_forget_fingerprint(Fingerprint *fprint,
171 int and_maybe_context);
172
173/* Forget a whole context, so long as it's PLAINTEXT. */
174void otrl_context_forget(ConnContext *context);
175
176/* Forget all the contexts in a given OtrlUserState. */
177void otrl_context_forget_all(OtrlUserState us);
178
179#endif
diff --git a/linden/indra/libotr/libotr-3.2.0/src/dh.c b/linden/indra/libotr/libotr-3.2.0/src/dh.c
new file mode 100755
index 0000000..610c84e
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/dh.c
@@ -0,0 +1,466 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/* system headers */
21#include <stdlib.h>
22
23/* libgcrypt headers */
24#include <gcrypt.h>
25
26/* libotr headers */
27#include "dh.h"
28
29static const char* DH1536_MODULUS_S = "0x"
30 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
31 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
32 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
33 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
34 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
35 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
36 "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
37 "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF";
38static const char *DH1536_GENERATOR_S = "0x02";
39static const int DH1536_MOD_LEN_BITS = 1536;
40static const int DH1536_MOD_LEN_BYTES = 192;
41
42static gcry_mpi_t DH1536_MODULUS = NULL;
43static gcry_mpi_t DH1536_MODULUS_MINUS_2 = NULL;
44static gcry_mpi_t DH1536_GENERATOR = NULL;
45
46/*
47 * Call this once, at plugin load time. It sets up the modulus and
48 * generator MPIs.
49 */
50void otrl_dh_init(void)
51{
52 gcry_mpi_scan(&DH1536_MODULUS, GCRYMPI_FMT_HEX, DH1536_MODULUS_S, 0, NULL);
53 gcry_mpi_scan(&DH1536_GENERATOR, GCRYMPI_FMT_HEX, DH1536_GENERATOR_S,
54 0, NULL);
55 DH1536_MODULUS_MINUS_2 = gcry_mpi_new(DH1536_MOD_LEN_BITS);
56 gcry_mpi_sub_ui(DH1536_MODULUS_MINUS_2, DH1536_MODULUS, 2);
57}
58
59/*
60 * Initialize the fields of a DH keypair.
61 */
62void otrl_dh_keypair_init(DH_keypair *kp)
63{
64 kp->groupid = 0;
65 kp->priv = NULL;
66 kp->pub = NULL;
67}
68
69/*
70 * Copy a DH_keypair.
71 */
72void otrl_dh_keypair_copy(DH_keypair *dst, const DH_keypair *src)
73{
74 dst->groupid = src->groupid;
75 dst->priv = gcry_mpi_copy(src->priv);
76 dst->pub = gcry_mpi_copy(src->pub);
77}
78
79/*
80 * Deallocate the contents of a DH_keypair (but not the DH_keypair
81 * itself)
82 */
83void otrl_dh_keypair_free(DH_keypair *kp)
84{
85 gcry_mpi_release(kp->priv);
86 gcry_mpi_release(kp->pub);
87 kp->priv = NULL;
88 kp->pub = NULL;
89}
90
91/*
92 * Generate a DH keypair for a specified group.
93 */
94gcry_error_t otrl_dh_gen_keypair(unsigned int groupid, DH_keypair *kp)
95{
96 unsigned char *secbuf = NULL;
97 gcry_mpi_t privkey = NULL;
98
99 if (groupid != DH1536_GROUP_ID) {
100 /* Invalid group id */
101 return gcry_error(GPG_ERR_INV_VALUE);
102 }
103
104 /* Generate the secret key: a random 320-bit value */
105 secbuf = gcry_random_bytes_secure(40, GCRY_STRONG_RANDOM);
106 gcry_mpi_scan(&privkey, GCRYMPI_FMT_USG, secbuf, 40, NULL);
107 gcry_free(secbuf);
108
109 kp->groupid = groupid;
110 kp->priv = privkey;
111 kp->pub = gcry_mpi_new(DH1536_MOD_LEN_BITS);
112 gcry_mpi_powm(kp->pub, DH1536_GENERATOR, privkey, DH1536_MODULUS);
113 return gcry_error(GPG_ERR_NO_ERROR);
114}
115
116/*
117 * Construct session keys from a DH keypair and someone else's public
118 * key.
119 */
120gcry_error_t otrl_dh_session(DH_sesskeys *sess, const DH_keypair *kp,
121 gcry_mpi_t y)
122{
123 gcry_mpi_t gab;
124 size_t gablen;
125 unsigned char *gabdata;
126 unsigned char *hashdata;
127 unsigned char sendbyte, rcvbyte;
128 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
129
130 otrl_dh_session_blank(sess);
131
132 if (kp->groupid != DH1536_GROUP_ID) {
133 /* Invalid group id */
134 return gcry_error(GPG_ERR_INV_VALUE);
135 }
136
137 /* Calculate the shared secret MPI */
138 gab = gcry_mpi_new(DH1536_MOD_LEN_BITS);
139 gcry_mpi_powm(gab, y, kp->priv, DH1536_MODULUS);
140
141 /* Output it in the right format */
142 gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &gablen, gab);
143 gabdata = gcry_malloc_secure(gablen + 5);
144 if (!gabdata) {
145 gcry_mpi_release(gab);
146 return gcry_error(GPG_ERR_ENOMEM);
147 }
148 gabdata[1] = (gablen >> 24) & 0xff;
149 gabdata[2] = (gablen >> 16) & 0xff;
150 gabdata[3] = (gablen >> 8) & 0xff;
151 gabdata[4] = gablen & 0xff;
152 gcry_mpi_print(GCRYMPI_FMT_USG, gabdata+5, gablen, NULL, gab);
153 gcry_mpi_release(gab);
154
155 hashdata = gcry_malloc_secure(20);
156 if (!hashdata) {
157 gcry_free(gabdata);
158 return gcry_error(GPG_ERR_ENOMEM);
159 }
160
161 /* Are we the "high" or "low" end of the connection? */
162 if ( gcry_mpi_cmp(kp->pub, y) > 0 ) {
163 sendbyte = 0x01;
164 rcvbyte = 0x02;
165 } else {
166 sendbyte = 0x02;
167 rcvbyte = 0x01;
168 }
169
170 /* Calculate the sending encryption key */
171 gabdata[0] = sendbyte;
172 gcry_md_hash_buffer(GCRY_MD_SHA1, hashdata, gabdata, gablen+5);
173 err = gcry_cipher_open(&(sess->sendenc), GCRY_CIPHER_AES,
174 GCRY_CIPHER_MODE_CTR, GCRY_CIPHER_SECURE);
175 if (err) goto err;
176 err = gcry_cipher_setkey(sess->sendenc, hashdata, 16);
177 if (err) goto err;
178
179 /* Calculate the sending MAC key */
180 gcry_md_hash_buffer(GCRY_MD_SHA1, sess->sendmackey, hashdata, 16);
181 err = gcry_md_open(&(sess->sendmac), GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
182 if (err) goto err;
183 err = gcry_md_setkey(sess->sendmac, sess->sendmackey, 20);
184 if (err) goto err;
185
186 /* Calculate the receiving encryption key */
187 gabdata[0] = rcvbyte;
188 gcry_md_hash_buffer(GCRY_MD_SHA1, hashdata, gabdata, gablen+5);
189 err = gcry_cipher_open(&(sess->rcvenc), GCRY_CIPHER_AES,
190 GCRY_CIPHER_MODE_CTR, GCRY_CIPHER_SECURE);
191 if (err) goto err;
192 err = gcry_cipher_setkey(sess->rcvenc, hashdata, 16);
193 if (err) goto err;
194
195 /* Calculate the receiving MAC key (and save it in the DH_sesskeys
196 * struct, so we can reveal it later) */
197 gcry_md_hash_buffer(GCRY_MD_SHA1, sess->rcvmackey, hashdata, 16);
198 err = gcry_md_open(&(sess->rcvmac), GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
199 if (err) goto err;
200 err = gcry_md_setkey(sess->rcvmac, sess->rcvmackey, 20);
201 if (err) goto err;
202
203 gcry_free(gabdata);
204 gcry_free(hashdata);
205 return gcry_error(GPG_ERR_NO_ERROR);
206err:
207 otrl_dh_session_free(sess);
208 gcry_free(gabdata);
209 gcry_free(hashdata);
210 return err;
211}
212
213/*
214 * Compute the secure session id, two encryption keys, and four MAC keys
215 * given our DH key and their DH public key.
216 */
217gcry_error_t otrl_dh_compute_v2_auth_keys(const DH_keypair *our_dh,
218 gcry_mpi_t their_pub, unsigned char *sessionid, size_t *sessionidlenp,
219 gcry_cipher_hd_t *enc_c, gcry_cipher_hd_t *enc_cp,
220 gcry_md_hd_t *mac_m1, gcry_md_hd_t *mac_m1p,
221 gcry_md_hd_t *mac_m2, gcry_md_hd_t *mac_m2p)
222{
223 gcry_mpi_t s;
224 size_t slen;
225 unsigned char *sdata;
226 unsigned char *hashdata;
227 unsigned char ctr[16];
228 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
229
230 *enc_c = NULL;
231 *enc_cp = NULL;
232 *mac_m1 = NULL;
233 *mac_m1p = NULL;
234 *mac_m2 = NULL;
235 *mac_m2p = NULL;
236 memset(ctr, 0, 16);
237
238 if (our_dh->groupid != DH1536_GROUP_ID) {
239 /* Invalid group id */
240 return gcry_error(GPG_ERR_INV_VALUE);
241 }
242
243 /* Check that their_pub is in range */
244 if (gcry_mpi_cmp_ui(their_pub, 2) < 0 ||
245 gcry_mpi_cmp(their_pub, DH1536_MODULUS_MINUS_2) > 0) {
246 /* Invalid pubkey */
247 return gcry_error(GPG_ERR_INV_VALUE);
248 }
249
250 /* Calculate the shared secret MPI */
251 s = gcry_mpi_new(DH1536_MOD_LEN_BITS);
252 gcry_mpi_powm(s, their_pub, our_dh->priv, DH1536_MODULUS);
253
254 /* Output it in the right format */
255 gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &slen, s);
256 sdata = gcry_malloc_secure(slen + 5);
257 if (!sdata) {
258 gcry_mpi_release(s);
259 return gcry_error(GPG_ERR_ENOMEM);
260 }
261 sdata[1] = (slen >> 24) & 0xff;
262 sdata[2] = (slen >> 16) & 0xff;
263 sdata[3] = (slen >> 8) & 0xff;
264 sdata[4] = slen & 0xff;
265 gcry_mpi_print(GCRYMPI_FMT_USG, sdata+5, slen, NULL, s);
266 gcry_mpi_release(s);
267
268 /* Calculate the session id */
269 hashdata = gcry_malloc_secure(32);
270 if (!hashdata) {
271 gcry_free(sdata);
272 return gcry_error(GPG_ERR_ENOMEM);
273 }
274 sdata[0] = 0x00;
275 gcry_md_hash_buffer(GCRY_MD_SHA256, hashdata, sdata, slen+5);
276 memmove(sessionid, hashdata, 8);
277 *sessionidlenp = 8;
278
279 /* Calculate the encryption keys */
280 sdata[0] = 0x01;
281 gcry_md_hash_buffer(GCRY_MD_SHA256, hashdata, sdata, slen+5);
282
283 err = gcry_cipher_open(enc_c, GCRY_CIPHER_AES,
284 GCRY_CIPHER_MODE_CTR, GCRY_CIPHER_SECURE);
285 if (err) goto err;
286 err = gcry_cipher_setkey(*enc_c, hashdata, 16);
287 if (err) goto err;
288 err = gcry_cipher_setctr(*enc_c, ctr, 16);
289 if (err) goto err;
290
291 err = gcry_cipher_open(enc_cp, GCRY_CIPHER_AES,
292 GCRY_CIPHER_MODE_CTR, GCRY_CIPHER_SECURE);
293 if (err) goto err;
294 err = gcry_cipher_setkey(*enc_cp, hashdata+16, 16);
295 if (err) goto err;
296 err = gcry_cipher_setctr(*enc_cp, ctr, 16);
297 if (err) goto err;
298
299 /* Calculate the MAC keys */
300 sdata[0] = 0x02;
301 gcry_md_hash_buffer(GCRY_MD_SHA256, hashdata, sdata, slen+5);
302 err = gcry_md_open(mac_m1, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
303 if (err) goto err;
304 err = gcry_md_setkey(*mac_m1, hashdata, 32);
305 if (err) goto err;
306
307 sdata[0] = 0x03;
308 gcry_md_hash_buffer(GCRY_MD_SHA256, hashdata, sdata, slen+5);
309 err = gcry_md_open(mac_m2, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
310 if (err) goto err;
311 err = gcry_md_setkey(*mac_m2, hashdata, 32);
312 if (err) goto err;
313
314 sdata[0] = 0x04;
315 gcry_md_hash_buffer(GCRY_MD_SHA256, hashdata, sdata, slen+5);
316 err = gcry_md_open(mac_m1p, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
317 if (err) goto err;
318 err = gcry_md_setkey(*mac_m1p, hashdata, 32);
319 if (err) goto err;
320
321 sdata[0] = 0x05;
322 gcry_md_hash_buffer(GCRY_MD_SHA256, hashdata, sdata, slen+5);
323 err = gcry_md_open(mac_m2p, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
324 if (err) goto err;
325 err = gcry_md_setkey(*mac_m2p, hashdata, 32);
326 if (err) goto err;
327
328 gcry_free(sdata);
329 gcry_free(hashdata);
330 return gcry_error(GPG_ERR_NO_ERROR);
331
332err:
333 gcry_cipher_close(*enc_c);
334 gcry_cipher_close(*enc_cp);
335 gcry_md_close(*mac_m1);
336 gcry_md_close(*mac_m1p);
337 gcry_md_close(*mac_m2);
338 gcry_md_close(*mac_m2p);
339 *enc_c = NULL;
340 *enc_cp = NULL;
341 *mac_m1 = NULL;
342 *mac_m1p = NULL;
343 *mac_m2 = NULL;
344 *mac_m2p = NULL;
345 gcry_free(sdata);
346 gcry_free(hashdata);
347 return err;
348}
349
350/*
351 * Compute the secure session id, given our DH key and their DH public
352 * key.
353 */
354gcry_error_t otrl_dh_compute_v1_session_id(const DH_keypair *our_dh,
355 gcry_mpi_t their_pub, unsigned char *sessionid, size_t *sessionidlenp,
356 OtrlSessionIdHalf *halfp)
357{
358 gcry_mpi_t s;
359 size_t slen;
360 unsigned char *sdata;
361 unsigned char *hashdata;
362
363 if (our_dh->groupid != DH1536_GROUP_ID) {
364 /* Invalid group id */
365 return gcry_error(GPG_ERR_INV_VALUE);
366 }
367
368 /* Check that their_pub is in range */
369 if (gcry_mpi_cmp_ui(their_pub, 2) < 0 ||
370 gcry_mpi_cmp(their_pub, DH1536_MODULUS_MINUS_2) > 0) {
371 /* Invalid pubkey */
372 return gcry_error(GPG_ERR_INV_VALUE);
373 }
374
375 /* Calculate the shared secret MPI */
376 s = gcry_mpi_new(DH1536_MOD_LEN_BITS);
377 gcry_mpi_powm(s, their_pub, our_dh->priv, DH1536_MODULUS);
378
379 /* Output it in the right format */
380 gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &slen, s);
381 sdata = gcry_malloc_secure(slen + 5);
382 if (!sdata) {
383 gcry_mpi_release(s);
384 return gcry_error(GPG_ERR_ENOMEM);
385 }
386 sdata[1] = (slen >> 24) & 0xff;
387 sdata[2] = (slen >> 16) & 0xff;
388 sdata[3] = (slen >> 8) & 0xff;
389 sdata[4] = slen & 0xff;
390 gcry_mpi_print(GCRYMPI_FMT_USG, sdata+5, slen, NULL, s);
391 gcry_mpi_release(s);
392
393 /* Calculate the session id */
394 hashdata = gcry_malloc_secure(20);
395 if (!hashdata) {
396 gcry_free(sdata);
397 return gcry_error(GPG_ERR_ENOMEM);
398 }
399 sdata[0] = 0x00;
400 gcry_md_hash_buffer(GCRY_MD_SHA1, hashdata, sdata, slen+5);
401 memmove(sessionid, hashdata, 20);
402 *sessionidlenp = 20;
403
404 /* Which half should be bold? */
405 if (gcry_mpi_cmp(our_dh->pub, their_pub) > 0) {
406 *halfp = OTRL_SESSIONID_SECOND_HALF_BOLD;
407 } else {
408 *halfp = OTRL_SESSIONID_FIRST_HALF_BOLD;
409 }
410
411 gcry_free(hashdata);
412 gcry_free(sdata);
413 return gcry_error(GPG_ERR_NO_ERROR);
414}
415
416/*
417 * Deallocate the contents of a DH_sesskeys (but not the DH_sesskeys
418 * itself)
419 */
420void otrl_dh_session_free(DH_sesskeys *sess)
421{
422 gcry_cipher_close(sess->sendenc);
423 gcry_cipher_close(sess->rcvenc);
424 gcry_md_close(sess->sendmac);
425 gcry_md_close(sess->rcvmac);
426
427 otrl_dh_session_blank(sess);
428}
429
430/*
431 * Blank out the contents of a DH_sesskeys (without releasing it)
432 */
433void otrl_dh_session_blank(DH_sesskeys *sess)
434{
435 sess->sendenc = NULL;
436 sess->sendmac = NULL;
437 sess->rcvenc = NULL;
438 sess->rcvmac = NULL;
439 memset(sess->sendctr, 0, 16);
440 memset(sess->rcvctr, 0, 16);
441 memset(sess->sendmackey, 0, 20);
442 memset(sess->rcvmackey, 0, 20);
443 sess->sendmacused = 0;
444 sess->rcvmacused = 0;
445}
446
447/* Increment the top half of a counter block */
448void otrl_dh_incctr(unsigned char *ctr)
449{
450 int i;
451 for (i=8;i;--i) {
452 if (++ctr[i-1]) break;
453 }
454}
455
456/* Compare two counter values (8 bytes each). Return 0 if ctr1 == ctr2,
457 * < 0 if ctr1 < ctr2 (as unsigned 64-bit values), > 0 if ctr1 > ctr2. */
458int otrl_dh_cmpctr(const unsigned char *ctr1, const unsigned char *ctr2)
459{
460 int i;
461 for (i=0;i<8;++i) {
462 int c = ctr1[i] - ctr2[i];
463 if (c) return c;
464 }
465 return 0;
466}
diff --git a/linden/indra/libotr/libotr-3.2.0/src/dh.h b/linden/indra/libotr/libotr-3.2.0/src/dh.h
new file mode 100755
index 0000000..d68328f
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/dh.h
@@ -0,0 +1,119 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef __DH_H__
21#define __DH_H__
22
23#define DH1536_GROUP_ID 5
24
25typedef struct {
26 unsigned int groupid;
27 gcry_mpi_t priv, pub;
28} DH_keypair;
29
30/* Which half of the secure session id should be shown in bold? */
31typedef enum {
32 OTRL_SESSIONID_FIRST_HALF_BOLD,
33 OTRL_SESSIONID_SECOND_HALF_BOLD
34} OtrlSessionIdHalf;
35
36typedef struct {
37 unsigned char sendctr[16];
38 unsigned char rcvctr[16];
39 gcry_cipher_hd_t sendenc;
40 gcry_cipher_hd_t rcvenc;
41 gcry_md_hd_t sendmac;
42 unsigned char sendmackey[20];
43 int sendmacused;
44 gcry_md_hd_t rcvmac;
45 unsigned char rcvmackey[20];
46 int rcvmacused;
47} DH_sesskeys;
48
49/*
50 * Call this once, at plugin load time. It sets up the modulus and
51 * generator MPIs.
52 */
53void otrl_dh_init(void);
54
55/*
56 * Initialize the fields of a DH keypair.
57 */
58void otrl_dh_keypair_init(DH_keypair *kp);
59
60/*
61 * Copy a DH_keypair.
62 */
63void otrl_dh_keypair_copy(DH_keypair *dst, const DH_keypair *src);
64
65/*
66 * Deallocate the contents of a DH_keypair (but not the DH_keypair
67 * itself)
68 */
69void otrl_dh_keypair_free(DH_keypair *kp);
70
71/*
72 * Generate a DH keypair for a specified group.
73 */
74gcry_error_t otrl_dh_gen_keypair(unsigned int groupid, DH_keypair *kp);
75
76/*
77 * Construct session keys from a DH keypair and someone else's public
78 * key.
79 */
80gcry_error_t otrl_dh_session(DH_sesskeys *sess, const DH_keypair *kp,
81 gcry_mpi_t y);
82
83/*
84 * Compute the secure session id, two encryption keys, and four MAC keys
85 * given our DH key and their DH public key.
86 */
87gcry_error_t otrl_dh_compute_v2_auth_keys(const DH_keypair *our_dh,
88 gcry_mpi_t their_pub, unsigned char *sessionid, size_t *sessionidlenp,
89 gcry_cipher_hd_t *enc_c, gcry_cipher_hd_t *enc_cp,
90 gcry_md_hd_t *mac_m1, gcry_md_hd_t *mac_m1p,
91 gcry_md_hd_t *mac_m2, gcry_md_hd_t *mac_m2p);
92
93/*
94 * Compute the secure session id, given our DH key and their DH public
95 * key.
96 */
97gcry_error_t otrl_dh_compute_v1_session_id(const DH_keypair *our_dh,
98 gcry_mpi_t their_pub, unsigned char *sessionid, size_t *sessionidlenp,
99 OtrlSessionIdHalf *halfp);
100
101/*
102 * Deallocate the contents of a DH_sesskeys (but not the DH_sesskeys
103 * itself)
104 */
105void otrl_dh_session_free(DH_sesskeys *sess);
106
107/*
108 * Blank out the contents of a DH_sesskeys (without releasing it)
109 */
110void otrl_dh_session_blank(DH_sesskeys *sess);
111
112/* Increment the top half of a counter block */
113void otrl_dh_incctr(unsigned char *ctr);
114
115/* Compare two counter values (8 bytes each). Return 0 if ctr1 == ctr2,
116 * < 0 if ctr1 < ctr2 (as unsigned 64-bit values), > 0 if ctr1 > ctr2. */
117int otrl_dh_cmpctr(const unsigned char *ctr1, const unsigned char *ctr2);
118
119#endif
diff --git a/linden/indra/libotr/libotr-3.2.0/src/mem.c b/linden/indra/libotr/libotr-3.2.0/src/mem.c
new file mode 100755
index 0000000..b2a2191
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/mem.c
@@ -0,0 +1,163 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/* Memory allocation routines for libgcrypt. All of the session key
21 * information gets allocated through here, so we can wipe it out when
22 * it's free()d. We don't use the built-in secmem functions of
23 * libgcrypt because you need to declare a fixed amount of it when you
24 * start up.
25 *
26 * Because "secure" and "insecure" allocations from libgcrypt will get
27 * handled the same way (since we're not going to be running as root,
28 * and so won't actually have pinned memory), pretend all allocated
29 * memory (but just from libgcrypt) is requested secure, and wipe it on
30 * free(). */
31
32/* Uncomment the following to add a check that our free() and realloc() only
33 * get called on things returned from our malloc(). */
34/* #define OTRL_MEM_MAGIC 0x31415926 */
35
36/* system headers */
37#ifdef OTRL_MEM_MAGIC
38#include <stdio.h>
39#endif
40#include <stdlib.h>
41
42/* libgcrypt headers */
43#include <gcrypt.h>
44
45/* libotr headers */
46#include "mem.h"
47
48static int header_size;
49
50static void *otrl_mem_malloc(size_t n)
51{
52 void *p;
53 size_t new_n = n;
54 new_n += header_size;
55
56 /* Check for overflow attack */
57 if (new_n < n) return NULL;
58 p = malloc(new_n);
59 if (p == NULL) return NULL;
60
61 ((size_t *)p)[0] = new_n; /* Includes header size */
62#ifdef OTRL_MEM_MAGIC
63 ((size_t *)p)[1] = OTRL_MEM_MAGIC;
64#endif
65
66 return (void *)((char *)p + header_size);
67}
68
69static int otrl_mem_is_secure(const void *p)
70{
71 return 1;
72}
73
74static void otrl_mem_free(void *p)
75{
76 void *real_p = (void *)((char *)p - header_size);
77 size_t n = ((size_t *)real_p)[0];
78#ifdef OTRL_MEM_MAGIC
79 if (((size_t *)real_p)[1] != OTRL_MEM_MAGIC) {
80 fprintf(stderr, "Illegal free!\n");
81 return;
82 }
83#endif
84
85 /* Wipe the memory (in the same way the built-in deallocator in
86 * libgcrypt would) */
87 memset(real_p, 0xff, n);
88 memset(real_p, 0xaa, n);
89 memset(real_p, 0x55, n);
90 memset(real_p, 0x00, n);
91
92 free(real_p);
93}
94
95static void *otrl_mem_realloc(void *p, size_t n)
96{
97 if (p == NULL) {
98 return otrl_mem_malloc(n);
99 } else if (n == 0) {
100 otrl_mem_free(p);
101 return NULL;
102 } else {
103 void *real_p = (void *)((char *)p - header_size);
104 void *new_p;
105 size_t old_n = ((size_t *)real_p)[0];
106#ifdef OTRL_MEM_MAGIC
107 size_t magic = ((size_t *)real_p)[1];
108#endif
109 size_t new_n = n;
110 new_n += header_size;
111
112 /* Check for overflow attack */
113 if (new_n < n) return NULL;
114
115#ifdef OTRL_MEM_MAGIC
116 if (magic != OTRL_MEM_MAGIC) {
117 fprintf(stderr, "Illegal realloc!\n");
118 return NULL;
119 }
120#endif
121
122 if (new_n < old_n) {
123 /* Overwrite the space we're about to stop using */
124 void *p = (void *)((char *)real_p + new_n);
125 size_t excess = old_n - new_n;
126 memset(p, 0xff, excess);
127 memset(p, 0xaa, excess);
128 memset(p, 0x55, excess);
129 memset(p, 0x00, excess);
130
131 /* We don't actually need to realloc() */
132 new_p = real_p;
133 } else {
134 new_p = realloc(real_p, new_n);
135 if (new_p == NULL) return NULL;
136 }
137
138 ((size_t *)new_p)[0] = new_n; /* Includes header size */
139 return (void *)((char *)new_p + header_size);
140 }
141}
142
143void otrl_mem_init(void)
144{
145 header_size = 8;
146#ifdef OTRL_MEM_MAGIC
147 if (header_size < 2*sizeof(size_t)) {
148 header_size = 2*sizeof(size_t);
149 }
150#else
151 if (header_size < sizeof(size_t)) {
152 header_size = sizeof(size_t);
153 }
154#endif
155
156 gcry_set_allocation_handler(
157 otrl_mem_malloc,
158 otrl_mem_malloc,
159 otrl_mem_is_secure,
160 otrl_mem_realloc,
161 otrl_mem_free
162 );
163}
diff --git a/linden/indra/libotr/libotr-3.2.0/src/mem.h b/linden/indra/libotr/libotr-3.2.0/src/mem.h
new file mode 100755
index 0000000..19e00cf
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/mem.h
@@ -0,0 +1,25 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef __MEM_H__
21#define __MEM_H__
22
23void otrl_mem_init(void);
24
25#endif
diff --git a/linden/indra/libotr/libotr-3.2.0/src/message.c b/linden/indra/libotr/libotr-3.2.0/src/message.c
new file mode 100755
index 0000000..75791b3
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/message.c
@@ -0,0 +1,1455 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/* system headers */
21#include <stdio.h>
22#include <stdlib.h>
23#include <time.h>
24
25/* libgcrypt headers */
26#include <gcrypt.h>
27
28/* libotr headers */
29#include "privkey.h"
30#include "proto.h"
31#include "auth.h"
32#include "message.h"
33#include "sm.h"
34
35/* The API version */
36extern unsigned int otrl_api_version;
37
38/* How long after sending a packet should we wait to send a heartbeat? */
39#define HEARTBEAT_INTERVAL 60
40
41/* How old are messages allowed to be in order to be candidates for
42 * resending in response to a rekey? */
43#define RESEND_INTERVAL 60
44
45/* Deallocate a message allocated by other otrl_message_* routines. */
46void otrl_message_free(char *message)
47{
48 free(message);
49}
50
51/* Handle a message about to be sent to the network. It is safe to pass
52 * all messages about to be sent to this routine. add_appdata is a
53 * function that will be called in the event that a new ConnContext is
54 * created. It will be passed the data that you supplied, as well as a
55 * pointer to the new ConnContext. You can use this to add
56 * application-specific information to the ConnContext using the
57 * "context->app" field, for example. If you don't need to do this, you
58 * can pass NULL for the last two arguments of otrl_message_sending.
59 *
60 * tlvs is a chain of OtrlTLVs to append to the private message. It is
61 * usually correct to just pass NULL here.
62 *
63 * If this routine returns non-zero, then the library tried to encrypt
64 * the message, but for some reason failed. DO NOT send the message in
65 * the clear in that case.
66 *
67 * If *messagep gets set by the call to something non-NULL, then you
68 * should replace your message with the contents of *messagep, and
69 * send that instead. Call otrl_message_free(*messagep) when you're
70 * done with it. */
71gcry_error_t otrl_message_sending(OtrlUserState us,
72 const OtrlMessageAppOps *ops,
73 void *opdata, const char *accountname, const char *protocol,
74 const char *recipient, const char *message, OtrlTLV *tlvs,
75 char **messagep,
76 void (*add_appdata)(void *data, ConnContext *context),
77 void *data)
78{
79 struct context * context;
80 char * msgtosend;
81 gcry_error_t err;
82 OtrlPolicy policy = OTRL_POLICY_DEFAULT;
83 int context_added = 0;
84
85 *messagep = NULL;
86
87 if (!accountname || !protocol || !recipient || !message || !messagep)
88 return gcry_error(GPG_ERR_NO_ERROR);
89
90 /* See if we have a fingerprint for this user */
91 context = otrl_context_find(us, recipient, accountname, protocol,
92 1, &context_added, add_appdata, data);
93
94 /* Update the context list if we added one */
95 if (context_added && ops->update_context_list) {
96 ops->update_context_list(opdata);
97 }
98
99 /* Check the policy */
100 if (ops->policy) {
101 policy = ops->policy(opdata, context);
102 }
103
104 /* Should we go on at all? */
105 if ((policy & OTRL_POLICY_VERSION_MASK) == 0) {
106 return gcry_error(GPG_ERR_NO_ERROR);
107 }
108
109 /* If this is an OTR Query message, don't encrypt it. */
110 if (otrl_proto_message_type(message) == OTRL_MSGTYPE_QUERY) {
111 /* Replace the "?OTR?" with a custom message */
112 char *bettermsg = otrl_proto_default_query_msg(accountname, policy);
113 if (bettermsg) {
114 *messagep = bettermsg;
115 }
116 return gcry_error(GPG_ERR_NO_ERROR);
117 }
118
119 /* What is the current message disposition? */
120 switch(context->msgstate) {
121 case OTRL_MSGSTATE_PLAINTEXT:
122 if ((policy & OTRL_POLICY_REQUIRE_ENCRYPTION)) {
123 /* We're trying to send an unencrypted message with a policy
124 * that disallows that. Don't do that, but try to start
125 * up OTR instead. */
126 if ((!(ops->display_otr_message) ||
127 ops->display_otr_message(opdata, accountname,
128 protocol, recipient, "Attempting to start a "
129 "private conversation...")) && ops->notify) {
130 const char *format = "You attempted to send an "
131 "unencrypted message to %s";
132 char *primary = malloc(strlen(format) +
133 strlen(recipient) - 1);
134 if (primary) {
135 sprintf(primary, format, recipient);
136 ops->notify(opdata, OTRL_NOTIFY_WARNING, accountname,
137 protocol, recipient, "OTR Policy Violation",
138 primary,
139 "Unencrypted messages to this recipient are "
140 "not allowed. Attempting to start a private "
141 "conversation.\n\nYour message will be "
142 "retransmitted when the private conversation "
143 "starts.");
144 free(primary);
145 }
146 }
147 context->lastmessage = gcry_malloc_secure(strlen(message) + 1);
148 if (context->lastmessage) {
149 char *bettermsg = otrl_proto_default_query_msg(accountname,
150 policy);
151 strcpy(context->lastmessage, message);
152 context->lastsent = time(NULL);
153 context->may_retransmit = 2;
154 if (bettermsg) {
155 *messagep = bettermsg;
156 } else {
157 return gcry_error(GPG_ERR_ENOMEM);
158 }
159 }
160 } else {
161 if ((policy & OTRL_POLICY_SEND_WHITESPACE_TAG) &&
162 context->otr_offer != OFFER_REJECTED) {
163 /* See if this user can speak OTR. Append the
164 * OTR_MESSAGE_TAG to the plaintext message, and see
165 * if he responds. */
166 size_t msglen = strlen(message);
167 size_t basetaglen = strlen(OTRL_MESSAGE_TAG_BASE);
168 size_t v1taglen = (policy & OTRL_POLICY_ALLOW_V1) ?
169 strlen(OTRL_MESSAGE_TAG_V1) : 0;
170 size_t v2taglen = (policy & OTRL_POLICY_ALLOW_V2) ?
171 strlen(OTRL_MESSAGE_TAG_V2) : 0;
172 char *taggedmsg = malloc(msglen + basetaglen + v1taglen
173 +v2taglen + 1);
174 if (taggedmsg) {
175 strcpy(taggedmsg, message);
176 strcpy(taggedmsg + msglen, OTRL_MESSAGE_TAG_BASE);
177 if (v1taglen) {
178 strcpy(taggedmsg + msglen + basetaglen,
179 OTRL_MESSAGE_TAG_V1);
180 }
181 if (v2taglen) {
182 strcpy(taggedmsg + msglen + basetaglen + v1taglen,
183 OTRL_MESSAGE_TAG_V2);
184 }
185 *messagep = taggedmsg;
186 if (context) {
187 context->otr_offer = OFFER_SENT;
188 }
189 }
190 }
191 }
192 break;
193 case OTRL_MSGSTATE_ENCRYPTED:
194 /* Create the new, encrypted message */
195 err = otrl_proto_create_data(&msgtosend, context, message, tlvs,
196 0);
197 if (!err) {
198 context->lastsent = time(NULL);
199 *messagep = msgtosend;
200 } else {
201 /* Uh, oh. Whatever we do, *don't* send the message in the
202 * clear. */
203 *messagep = strdup("?OTR Error: Error occurred encrypting "
204 "message");
205 if ((!(ops->display_otr_message) ||
206 ops->display_otr_message(opdata, accountname,
207 protocol, recipient, "An error occurred when "
208 "encrypting your message. The message was not "
209 "sent.")) && ops->notify) {
210 ops->notify(opdata, OTRL_NOTIFY_ERROR,
211 accountname, protocol, recipient,
212 "Error encrypting message",
213 "An error occurred when encrypting your message",
214 "The message was not sent.");
215 }
216 if (!(*messagep)) {
217 return gcry_error(GPG_ERR_ENOMEM);
218 }
219 }
220 break;
221 case OTRL_MSGSTATE_FINISHED:
222 *messagep = strdup("");
223 if ((!(ops->display_otr_message) ||
224 ops->display_otr_message(opdata, accountname,
225 protocol, recipient, "Your message was not sent. "
226 "Either end your private conversation, or restart "
227 "it.")) && ops->notify) {
228 const char *fmt = "%s has already closed his/her private "
229 "connection to you";
230 char *primary = malloc(strlen(fmt) + strlen(recipient) - 1);
231 if (primary) {
232 sprintf(primary, fmt, recipient);
233 ops->notify(opdata, OTRL_NOTIFY_ERROR,
234 accountname, protocol, recipient,
235 "Private connection closed", primary,
236 "Your message was not sent. Either close your "
237 "private connection to him, or refresh it.");
238 }
239 }
240 if (!(*messagep)) {
241 return gcry_error(GPG_ERR_ENOMEM);
242 }
243 break;
244 }
245
246 return gcry_error(GPG_ERR_NO_ERROR);
247}
248
249/* If err == 0, send the last auth message for the given context to the
250 * appropriate user. Otherwise, display an appripriate error dialog.
251 * Return the value of err that was passed. */
252static gcry_error_t send_or_error_auth(const OtrlMessageAppOps *ops,
253 void *opdata, gcry_error_t err, ConnContext *context)
254{
255 if (!err) {
256 const char *msg = context->auth.lastauthmsg;
257 if (msg && *msg) {
258 otrl_message_fragment_and_send(ops, opdata, context, msg, OTRL_FRAGMENT_SEND_ALL, NULL);
259 /*if (ops->inject_message) {
260 ops->inject_message(opdata, context->accountname,
261 context->protocol, context->username, msg);
262 }*/
263 }
264 } else {
265 const char *buf_format = "Error setting up private conversation: %s";
266 const char *strerr;
267 char *buf;
268
269 switch(gcry_err_code(err)) {
270 case GPG_ERR_INV_VALUE:
271 strerr = "Malformed message received";
272 break;
273 default:
274 strerr = gcry_strerror(err);
275 break;
276 }
277 buf = malloc(strlen(buf_format) + strlen(strerr) - 1);
278 if (buf) {
279 sprintf(buf, buf_format, strerr);
280 }
281 if ((!(ops->display_otr_message) ||
282 ops->display_otr_message(opdata, context->accountname,
283 context->protocol, context->username, buf))
284 && ops->notify) {
285 ops->notify(opdata, OTRL_NOTIFY_ERROR, context->accountname,
286 context->protocol, context->username, "OTR error",
287 buf, NULL);
288 }
289 free(buf);
290 }
291 return err;
292}
293
294typedef struct {
295 int gone_encrypted;
296 OtrlUserState us;
297 const OtrlMessageAppOps *ops;
298 void *opdata;
299 ConnContext *context;
300 int ignore_message;
301 char **messagep;
302} EncrData;
303
304static gcry_error_t go_encrypted(const OtrlAuthInfo *auth, void *asdata)
305{
306 EncrData *edata = asdata;
307 gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
308 Fingerprint *found_print = NULL;
309 int fprint_added = 0;
310 OtrlMessageState oldstate = edata->context->msgstate;
311 Fingerprint *oldprint = edata->context->active_fingerprint;
312
313 /* See if we're talking to ourselves */
314 if (!gcry_mpi_cmp(auth->their_pub, auth->our_dh.pub)) {
315 /* Yes, we are. */
316 if ((!(edata->ops->display_otr_message) ||
317 edata->ops->display_otr_message(edata->opdata,
318 edata->context->accountname, edata->context->protocol,
319 edata->context->username,
320 "We are receiving our own OTR messages. "
321 "You are either trying to talk to yourself, "
322 "or someone is reflecting your messages back "
323 "at you.")) && edata->ops->notify) {
324 edata->ops->notify(edata->opdata, OTRL_NOTIFY_ERROR,
325 edata->context->accountname, edata->context->protocol,
326 edata->context->username, "OTR Error",
327 "We are receiving our own OTR messages.",
328 "You are either trying to talk to yourself, "
329 "or someone is reflecting your messages back "
330 "at you.");
331 }
332 edata->ignore_message = 1;
333 return gcry_error(GPG_ERR_NO_ERROR);
334 }
335
336 found_print = otrl_context_find_fingerprint(edata->context,
337 edata->context->auth.their_fingerprint, 1, &fprint_added);
338
339 if (fprint_added) {
340 /* Inform the user of the new fingerprint */
341 if (edata->ops->new_fingerprint) {
342 edata->ops->new_fingerprint(edata->opdata, edata->us,
343 edata->context->accountname, edata->context->protocol,
344 edata->context->username,
345 edata->context->auth.their_fingerprint);
346 }
347 /* Arrange that the new fingerprint be written to disk */
348 if (edata->ops->write_fingerprints) {
349 edata->ops->write_fingerprints(edata->opdata);
350 }
351 }
352
353 /* Is this a new session or just a refresh of an existing one? */
354 if (edata->context->msgstate == OTRL_MSGSTATE_ENCRYPTED &&
355 oldprint == found_print &&
356 edata->context->our_keyid - 1 == edata->context->auth.our_keyid &&
357 !gcry_mpi_cmp(edata->context->our_old_dh_key.pub,
358 edata->context->auth.our_dh.pub) &&
359 ((edata->context->their_keyid > 0 &&
360 edata->context->their_keyid ==
361 edata->context->auth.their_keyid &&
362 !gcry_mpi_cmp(edata->context->their_y,
363 edata->context->auth.their_pub)) ||
364 (edata->context->their_keyid > 1 &&
365 edata->context->their_keyid - 1 ==
366 edata->context->auth.their_keyid &&
367 edata->context->their_old_y != NULL &&
368 !gcry_mpi_cmp(edata->context->their_old_y,
369 edata->context->auth.their_pub)))) {
370 /* This is just a refresh of the existing session. */
371 if (edata->ops->still_secure) {
372 edata->ops->still_secure(edata->opdata, edata->context,
373 edata->context->auth.initiated);
374 }
375 edata->ignore_message = 1;
376 return gcry_error(GPG_ERR_NO_ERROR);
377 }
378
379 /* Copy the information from the auth into the context */
380 memmove(edata->context->sessionid,
381 edata->context->auth.secure_session_id, 20);
382 edata->context->sessionid_len =
383 edata->context->auth.secure_session_id_len;
384 edata->context->sessionid_half =
385 edata->context->auth.session_id_half;
386 edata->context->protocol_version =
387 edata->context->auth.protocol_version;
388
389 edata->context->their_keyid = edata->context->auth.their_keyid;
390 gcry_mpi_release(edata->context->their_y);
391 gcry_mpi_release(edata->context->their_old_y);
392 edata->context->their_y = gcry_mpi_copy(edata->context->auth.their_pub);
393 edata->context->their_old_y = NULL;
394
395 if (edata->context->our_keyid - 1 != edata->context->auth.our_keyid ||
396 gcry_mpi_cmp(edata->context->our_old_dh_key.pub,
397 edata->context->auth.our_dh.pub)) {
398 otrl_dh_keypair_free(&(edata->context->our_dh_key));
399 otrl_dh_keypair_free(&(edata->context->our_old_dh_key));
400 otrl_dh_keypair_copy(&(edata->context->our_old_dh_key),
401 &(edata->context->auth.our_dh));
402 otrl_dh_gen_keypair(edata->context->our_old_dh_key.groupid,
403 &(edata->context->our_dh_key));
404 edata->context->our_keyid = edata->context->auth.our_keyid + 1;
405 }
406
407 /* Create the session keys from the DH keys */
408 otrl_dh_session_free(&(edata->context->sesskeys[0][0]));
409 err = otrl_dh_session(&(edata->context->sesskeys[0][0]),
410 &(edata->context->our_dh_key), edata->context->their_y);
411 if (err) return err;
412 otrl_dh_session_free(&(edata->context->sesskeys[1][0]));
413 err = otrl_dh_session(&(edata->context->sesskeys[1][0]),
414 &(edata->context->our_old_dh_key), edata->context->their_y);
415 if (err) return err;
416
417 edata->context->generation++;
418 edata->context->active_fingerprint = found_print;
419 edata->context->msgstate = OTRL_MSGSTATE_ENCRYPTED;
420
421 if (edata->ops->update_context_list) {
422 edata->ops->update_context_list(edata->opdata);
423 }
424 if (oldstate == OTRL_MSGSTATE_ENCRYPTED && oldprint == found_print) {
425 if (edata->ops->still_secure) {
426 edata->ops->still_secure(edata->opdata, edata->context,
427 edata->context->auth.initiated);
428 }
429 } else {
430 if (edata->ops->gone_secure) {
431 edata->ops->gone_secure(edata->opdata, edata->context);
432 }
433 }
434
435 edata->gone_encrypted = 1;
436
437 return gpg_error(GPG_ERR_NO_ERROR);
438}
439
440static void maybe_resend(EncrData *edata)
441{
442 gcry_error_t err;
443 time_t now;
444
445 if (!edata->gone_encrypted) return;
446
447 /* See if there's a message we sent recently that should be resent. */
448 now = time(NULL);
449 if (edata->context->lastmessage != NULL &&
450 edata->context->may_retransmit &&
451 edata->context->lastsent >= (now - RESEND_INTERVAL)) {
452 char *resendmsg;
453 int resending = (edata->context->may_retransmit == 1);
454
455 /* Re-encrypt the message with the new keys */
456 err = otrl_proto_create_data(&resendmsg,
457 edata->context, edata->context->lastmessage, NULL, 0);
458 if (!err) {
459 //const char *format = "The last message "
460 //"to %s was resent.";
461 //char *buf;
462
463 /* Resend the message */
464 otrl_message_fragment_and_send(edata->ops, edata->opdata, edata->context, resendmsg, OTRL_FRAGMENT_SEND_ALL, NULL);
465 free(resendmsg);
466 edata->context->lastsent = now;
467
468 if (!resending) {
469 /* We're actually just sending it
470 * for the first time. */
471 edata->ignore_message = 1;
472 } /*else {
473 // Let the user know we resent it
474 buf = malloc(strlen(format) +
475 strlen(edata->context->username) - 1);
476 if (buf) {
477 sprintf(buf, format, edata->context->username);
478 if (edata->ops->display_otr_message) {
479 if (!edata->ops->display_otr_message(
480 edata->opdata, edata->context->accountname,
481 edata->context->protocol,
482 edata->context->username, buf)) {
483 edata->ignore_message = 1;
484 }
485 }
486 if (edata->ignore_message != 1) {
487 *(edata->messagep) = buf;
488 edata->ignore_message = 0;
489 } else {
490 free(buf);
491 }
492 }
493 }*/
494 }
495 }
496}
497
498/* Set the trust level based on the result of the SMP */
499static void set_smp_trust(const OtrlMessageAppOps *ops, void *opdata,
500 ConnContext *context, int trusted)
501{
502 otrl_context_set_trust(context->active_fingerprint, trusted ? "smp" : "");
503
504 /* Write the new info to disk, redraw the ui, and redraw the
505 * OTR buttons. */
506 if (ops->write_fingerprints) {
507 ops->write_fingerprints(opdata);
508 }
509}
510
511static void init_respond_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
512 void *opdata, ConnContext *context, const char *question,
513 const unsigned char *secret, size_t secretlen, int initiating)
514{
515 unsigned char *smpmsg = NULL;
516 int smpmsglen;
517 unsigned char combined_secret[SM_DIGEST_SIZE];
518 gcry_error_t err;
519 unsigned char our_fp[20];
520 unsigned char *combined_buf;
521 size_t combined_buf_len;
522 OtrlTLV *sendtlv;
523 char *sendsmp = NULL;
524
525 if (!context || context->msgstate != OTRL_MSGSTATE_ENCRYPTED) return;
526
527 /*
528 * Construct the combined secret as a SHA256 hash of:
529 * Version byte (0x01), Initiator fingerprint (20 bytes),
530 * responder fingerprint (20 bytes), secure session id, input secret
531 */
532 otrl_privkey_fingerprint_raw(us, our_fp, context->accountname,
533 context->protocol);
534
535 combined_buf_len = 41 + context->sessionid_len + secretlen;
536 combined_buf = malloc(combined_buf_len);
537 combined_buf[0] = 0x01;
538 if (initiating) {
539 memmove(combined_buf + 1, our_fp, 20);
540 memmove(combined_buf + 21,
541 context->active_fingerprint->fingerprint, 20);
542 } else {
543 memmove(combined_buf + 1,
544 context->active_fingerprint->fingerprint, 20);
545 memmove(combined_buf + 21, our_fp, 20);
546 }
547 memmove(combined_buf + 41, context->sessionid,
548 context->sessionid_len);
549 memmove(combined_buf + 41 + context->sessionid_len,
550 secret, secretlen);
551 gcry_md_hash_buffer(SM_HASH_ALGORITHM, combined_secret, combined_buf,
552 combined_buf_len);
553 free(combined_buf);
554
555 if (initiating) {
556 otrl_sm_step1(context->smstate, combined_secret, SM_DIGEST_SIZE,
557 &smpmsg, &smpmsglen);
558 } else {
559 otrl_sm_step2b(context->smstate, combined_secret, SM_DIGEST_SIZE,
560 &smpmsg, &smpmsglen);
561 }
562
563 /* If we've got a question, attach it to the smpmsg */
564 if (question != NULL) {
565 size_t qlen = strlen(question);
566 unsigned char *qsmpmsg = malloc(qlen + 1 + smpmsglen);
567 if (!qsmpmsg) {
568 free(smpmsg);
569 return;
570 }
571 strcpy((char *)qsmpmsg, question);
572 memmove(qsmpmsg + qlen + 1, smpmsg, smpmsglen);
573 free(smpmsg);
574 smpmsg = qsmpmsg;
575 smpmsglen += qlen + 1;
576 }
577
578 /* Send msg with next smp msg content */
579 sendtlv = otrl_tlv_new(initiating ?
580 (question != NULL ? OTRL_TLV_SMP1Q : OTRL_TLV_SMP1)
581 : OTRL_TLV_SMP2,
582 smpmsglen, smpmsg);
583 err = otrl_proto_create_data(&sendsmp, context, "", sendtlv,
584 OTRL_MSGFLAGS_IGNORE_UNREADABLE);
585 if (!err) {
586 /* Send it, and set the next expected message to the
587 * logical response */
588 err = otrl_message_fragment_and_send(ops, opdata, context,
589 sendsmp, OTRL_FRAGMENT_SEND_ALL, NULL);
590 context->smstate->nextExpected =
591 initiating ? OTRL_SMP_EXPECT2 : OTRL_SMP_EXPECT3;
592 }
593 free(sendsmp);
594 otrl_tlv_free(sendtlv);
595 free(smpmsg);
596}
597
598/* Initiate the Socialist Millionaires' Protocol */
599void otrl_message_initiate_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
600 void *opdata, ConnContext *context, const unsigned char *secret,
601 size_t secretlen)
602{
603 init_respond_smp(us, ops, opdata, context, NULL, secret, secretlen, 1);
604}
605
606/* Initiate the Socialist Millionaires' Protocol and send a prompt
607 * question to the buddy */
608void otrl_message_initiate_smp_q(OtrlUserState us,
609 const OtrlMessageAppOps *ops, void *opdata, ConnContext *context,
610 const char *question, const unsigned char *secret, size_t secretlen)
611{
612 init_respond_smp(us, ops, opdata, context, question, secret, secretlen, 1);
613}
614
615/* Respond to a buddy initiating the Socialist Millionaires' Protocol */
616void otrl_message_respond_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
617 void *opdata, ConnContext *context, const unsigned char *secret,
618 size_t secretlen)
619{
620 init_respond_smp(us, ops, opdata, context, NULL, secret, secretlen, 0);
621}
622
623/* Abort the SMP. Called when an unexpected SMP message breaks the
624 * normal flow. */
625void otrl_message_abort_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
626 void *opdata, ConnContext *context)
627{
628 OtrlTLV *sendtlv = otrl_tlv_new(OTRL_TLV_SMP_ABORT, 0,
629 (const unsigned char *)"");
630 char *sendsmp = NULL;
631 gcry_error_t err;
632
633 context->smstate->nextExpected = OTRL_SMP_EXPECT1;
634
635 err = otrl_proto_create_data(&sendsmp,
636 context, "", sendtlv,
637 OTRL_MSGFLAGS_IGNORE_UNREADABLE);
638 if (!err) {
639 /* Send the abort signal so our buddy knows we've stopped */
640 err = otrl_message_fragment_and_send(ops, opdata, context,
641 sendsmp, OTRL_FRAGMENT_SEND_ALL, NULL);
642 }
643 free(sendsmp);
644 otrl_tlv_free(sendtlv);
645}
646
647/* Handle a message just received from the network. It is safe to pass
648 * all received messages to this routine. add_appdata is a function
649 * that will be called in the event that a new ConnContext is created.
650 * It will be passed the data that you supplied, as well as
651 * a pointer to the new ConnContext. You can use this to add
652 * application-specific information to the ConnContext using the
653 * "context->app" field, for example. If you don't need to do this, you
654 * can pass NULL for the last two arguments of otrl_message_receiving.
655 *
656 * If otrl_message_receiving returns 1, then the message you received
657 * was an internal protocol message, and no message should be delivered
658 * to the user.
659 *
660 * If it returns 0, then check if *messagep was set to non-NULL. If
661 * so, replace the received message with the contents of *messagep, and
662 * deliver that to the user instead. You must call
663 * otrl_message_free(*messagep) when you're done with it. If tlvsp is
664 * non-NULL, *tlvsp will be set to a chain of any TLVs that were
665 * transmitted along with this message. You must call
666 * otrl_tlv_free(*tlvsp) when you're done with those.
667 *
668 * If otrl_message_receiving returns 0 and *messagep is NULL, then this
669 * was an ordinary, non-OTR message, which should just be delivered to
670 * the user without modification. */
671int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
672 void *opdata, const char *accountname, const char *protocol,
673 const char *sender, const char *message, char **newmessagep,
674 OtrlTLV **tlvsp,
675 void (*add_appdata)(void *data, ConnContext *context),
676 void *data)
677{
678 ConnContext *context;
679 OtrlMessageType msgtype;
680 int context_added = 0;
681 OtrlMessageState msgstate;
682 OtrlPolicy policy = OTRL_POLICY_DEFAULT;
683 int fragment_assembled = 0;
684 char *unfragmessage = NULL;
685 EncrData edata;
686
687 if (!accountname || !protocol || !sender || !message || !newmessagep)
688 return 0;
689
690 *newmessagep = NULL;
691 if (tlvsp) *tlvsp = NULL;
692
693 /* Find our context and state with this correspondent */
694 context = otrl_context_find(us, sender, accountname,
695 protocol, 1, &context_added, add_appdata, data);
696
697 /* Update the context list if we added one */
698 if (context_added && ops->update_context_list) {
699 ops->update_context_list(opdata);
700 }
701
702 /* Check the policy */
703 if (ops->policy) {
704 policy = ops->policy(opdata, context);
705 }
706
707 /* Should we go on at all? */
708 if ((policy & OTRL_POLICY_VERSION_MASK) == 0) {
709 return 0;
710 }
711
712 /* See if we have a fragment */
713 switch(otrl_proto_fragment_accumulate(&unfragmessage, context, message)) {
714 case OTRL_FRAGMENT_UNFRAGMENTED:
715 /* Do nothing */
716 break;
717 case OTRL_FRAGMENT_INCOMPLETE:
718 /* We've accumulated this fragment, but we don't have a
719 * complete message yet */
720 return 1;
721 case OTRL_FRAGMENT_COMPLETE:
722 /* We've got a new complete message, in unfragmessage. */
723 fragment_assembled = 1;
724 message = unfragmessage;
725 break;
726 }
727
728 /* What type of message is it? Note that this just checks the
729 * header; it's not necessarily a _valid_ message of this type. */
730 msgtype = otrl_proto_message_type(message);
731 msgstate = context->msgstate;
732
733 /* See if they responded to our OTR offer */
734 if ((policy & OTRL_POLICY_SEND_WHITESPACE_TAG)) {
735 if (msgtype != OTRL_MSGTYPE_NOTOTR) {
736 context->otr_offer = OFFER_ACCEPTED;
737 } else if (context->otr_offer == OFFER_SENT) {
738 context->otr_offer = OFFER_REJECTED;
739 }
740 }
741
742 edata.gone_encrypted = 0;
743 edata.us = us;
744 edata.context = context;
745 edata.ops = ops;
746 edata.opdata = opdata;
747 edata.ignore_message = -1;
748 edata.messagep = newmessagep;
749
750 switch(msgtype) {
751 unsigned int bestversion;
752 const char *startwhite, *endwhite;
753 DH_keypair *our_dh;
754 unsigned int our_keyid;
755 OtrlPrivKey *privkey;
756 gcry_error_t err;
757 int haveauthmsg;
758 case OTRL_MSGTYPE_QUERY:
759 /* See if we should use an existing DH keypair, or generate
760 * a fresh one. */
761 if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
762 our_dh = &(context->our_old_dh_key);
763 our_keyid = context->our_keyid - 1;
764 } else {
765 our_dh = NULL;
766 our_keyid = 0;
767 }
768
769 /* Find the best version of OTR that we both speak */
770 switch(otrl_proto_query_bestversion(message, policy)) {
771 case 2:
772 err = otrl_auth_start_v2(&(context->auth));
773 send_or_error_auth(ops, opdata, err, context);
774 break;
775 case 1:
776 /* Get our private key */
777 privkey = otrl_privkey_find(us, context->accountname,
778 context->protocol);
779 if (privkey == NULL) {
780 /* We've got no private key! */
781 if (ops->create_privkey) {
782 ops->create_privkey(opdata, context->accountname,
783 context->protocol);
784 privkey = otrl_privkey_find(us,
785 context->accountname, context->protocol);
786 }
787 }
788 if (privkey) {
789 err = otrl_auth_start_v1(&(context->auth), our_dh,
790 our_keyid, privkey);
791 send_or_error_auth(ops, opdata, err, context);
792 }
793 break;
794 default:
795 /* Just ignore this message */
796 break;
797 }
798 /* Don't display the Query message to the user. */
799 if (edata.ignore_message == -1) edata.ignore_message = 1;
800 break;
801
802 case OTRL_MSGTYPE_DH_COMMIT:
803 if ((policy & OTRL_POLICY_ALLOW_V2)) {
804 err = otrl_auth_handle_commit(&(context->auth), message);
805 send_or_error_auth(ops, opdata, err, context);
806 }
807
808 if (edata.ignore_message == -1) edata.ignore_message = 1;
809 break;
810
811 case OTRL_MSGTYPE_DH_KEY:
812 if ((policy & OTRL_POLICY_ALLOW_V2)) {
813 /* Get our private key */
814 privkey = otrl_privkey_find(us, context->accountname,
815 context->protocol);
816 if (privkey == NULL) {
817 /* We've got no private key! */
818 if (ops->create_privkey) {
819 ops->create_privkey(opdata, context->accountname,
820 context->protocol);
821 privkey = otrl_privkey_find(us,
822 context->accountname, context->protocol);
823 }
824 }
825 if (privkey) {
826 err = otrl_auth_handle_key(&(context->auth), message,
827 &haveauthmsg, privkey);
828 if (err || haveauthmsg) {
829 send_or_error_auth(ops, opdata, err, context);
830 }
831 }
832 }
833
834 if (edata.ignore_message == -1) edata.ignore_message = 1;
835 break;
836
837 case OTRL_MSGTYPE_REVEALSIG:
838 if ((policy & OTRL_POLICY_ALLOW_V2)) {
839 /* Get our private key */
840 privkey = otrl_privkey_find(us, context->accountname,
841 context->protocol);
842 if (privkey == NULL) {
843 /* We've got no private key! */
844 if (ops->create_privkey) {
845 ops->create_privkey(opdata, context->accountname,
846 context->protocol);
847 privkey = otrl_privkey_find(us,
848 context->accountname, context->protocol);
849 }
850 }
851 if (privkey) {
852 err = otrl_auth_handle_revealsig(&(context->auth),
853 message, &haveauthmsg, privkey, go_encrypted,
854 &edata);
855 if (err || haveauthmsg) {
856 send_or_error_auth(ops, opdata, err, context);
857 maybe_resend(&edata);
858 }
859 }
860 }
861
862 if (edata.ignore_message == -1) edata.ignore_message = 1;
863 break;
864
865 case OTRL_MSGTYPE_SIGNATURE:
866 if ((policy & OTRL_POLICY_ALLOW_V2)) {
867 err = otrl_auth_handle_signature(&(context->auth),
868 message, &haveauthmsg, go_encrypted, &edata);
869 if (err || haveauthmsg) {
870 send_or_error_auth(ops, opdata, err, context);
871 maybe_resend(&edata);
872 }
873 }
874
875 if (edata.ignore_message == -1) edata.ignore_message = 1;
876 break;
877
878 case OTRL_MSGTYPE_V1_KEYEXCH:
879 if ((policy & OTRL_POLICY_ALLOW_V1)) {
880 /* See if we should use an existing DH keypair, or generate
881 * a fresh one. */
882 if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
883 our_dh = &(context->our_old_dh_key);
884 our_keyid = context->our_keyid - 1;
885 } else {
886 our_dh = NULL;
887 our_keyid = 0;
888 }
889
890 /* Get our private key */
891 privkey = otrl_privkey_find(us, context->accountname,
892 context->protocol);
893 if (privkey == NULL) {
894 /* We've got no private key! */
895 if (ops->create_privkey) {
896 ops->create_privkey(opdata, context->accountname,
897 context->protocol);
898 privkey = otrl_privkey_find(us,
899 context->accountname, context->protocol);
900 }
901 }
902 if (privkey) {
903 err = otrl_auth_handle_v1_key_exchange(&(context->auth),
904 message, &haveauthmsg, privkey, our_dh, our_keyid,
905 go_encrypted, &edata);
906 if (err || haveauthmsg) {
907 send_or_error_auth(ops, opdata, err, context);
908 maybe_resend(&edata);
909 }
910 }
911 }
912
913 if (edata.ignore_message == -1) edata.ignore_message = 1;
914 break;
915
916 case OTRL_MSGTYPE_DATA:
917 switch(context->msgstate) {
918 gcry_error_t err;
919 OtrlTLV *tlvs, *tlv;
920 char *plaintext;
921 char *buf;
922 const char *format;
923 const char *displayaccountname;
924 unsigned char flags;
925 NextExpectedSMP nextMsg;
926
927 case OTRL_MSGSTATE_PLAINTEXT:
928 case OTRL_MSGSTATE_FINISHED:
929 /* See if we're supposed to ignore this message in
930 * the event it's unreadable. */
931 err = otrl_proto_data_read_flags(message, &flags);
932 if ((flags & OTRL_MSGFLAGS_IGNORE_UNREADABLE)) {
933 edata.ignore_message = 1;
934 break;
935 }
936
937 /* Don't use g_strdup_printf here, because someone
938 * (not us) is going to free() the *newmessagep pointer,
939 * not g_free() it. */
940 format = "The encrypted message received from %s is "
941 "unreadable, as you are not currently communicating "
942 "privately.";
943 buf = malloc(strlen(format) + strlen(context->username)
944 - 1); /* Remove "%s", add username + '\0' */
945 if (buf) {
946 sprintf(buf, format, context->username);
947 if (ops->display_otr_message) {
948 if (!ops->display_otr_message(opdata, accountname,
949 protocol, sender, buf)) {
950 edata.ignore_message = 1;
951 }
952 }
953 if (edata.ignore_message != 1) {
954 *newmessagep = buf;
955 edata.ignore_message = 0;
956 } else {
957 free(buf);
958 }
959 }
960 format = "?OTR Error: You sent encrypted "
961 "data to %s, who wasn't expecting it.";
962 if (otrl_api_version >= 0x00030100 &&
963 ops->account_name) {
964 displayaccountname = ops->account_name(opdata,
965 context->accountname, protocol);
966 } else {
967 displayaccountname = NULL;
968 }
969 buf = malloc(strlen(format) + strlen(displayaccountname ?
970 displayaccountname : context->accountname)
971 - 1);
972 if (buf) {
973 sprintf(buf, format, displayaccountname ?
974 displayaccountname : context->accountname);
975 if (ops->inject_message) {
976 ops->inject_message(opdata, accountname, protocol,
977 sender, buf);
978 }
979 free(buf);
980 }
981 if (displayaccountname && otrl_api_version >= 0x00030100 &&
982 ops->account_name_free) {
983 ops->account_name_free(opdata, displayaccountname);
984 }
985
986 break;
987
988 case OTRL_MSGSTATE_ENCRYPTED:
989 err = otrl_proto_accept_data(&plaintext, &tlvs, context,
990 message, &flags);
991 if (err) {
992 int is_conflict =
993 (gpg_err_code(err) == GPG_ERR_CONFLICT);
994 if ((flags & OTRL_MSGFLAGS_IGNORE_UNREADABLE)) {
995 edata.ignore_message = 1;
996 break;
997 }/*
998 format = is_conflict ? "We received an unreadable "
999 "encrypted message from %s." :
1000 "We received a malformed data message from %s.";
1001 buf = malloc(strlen(format) + strlen(sender) - 1);
1002 if (buf) {
1003 sprintf(buf, format, sender);
1004 if ((!(ops->display_otr_message) ||
1005 ops->display_otr_message(opdata,
1006 accountname, protocol, sender,
1007 buf)) && ops->notify) {
1008 ops->notify(opdata, OTRL_NOTIFY_ERROR,
1009 accountname, protocol, sender,
1010 "OTR Error", buf, NULL);
1011 }
1012 free(buf);
1013 }*/
1014 if (ops->inject_message) {
1015 ops->inject_message(opdata, accountname, protocol,
1016 sender, is_conflict ? "?OTR Error: "
1017 "You sent an unreadable "
1018 "message. It has been resent." :
1019 "?OTR Error: You sent "
1020 "a malformed message, it has been resent.");
1021 }
1022 edata.ignore_message = 1;
1023 break;
1024 }
1025
1026 /* If the other side told us he's disconnected his
1027 * private connection, make a note of that so we
1028 * don't try sending anything else to him. */
1029 if (otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED)) {
1030 otrl_context_force_finished(context);
1031 }
1032
1033 /* If TLVs contain SMP data, process it */
1034 nextMsg = context->smstate->nextExpected;
1035 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q);
1036 if (tlv && nextMsg == OTRL_SMP_EXPECT1) {
1037 /* We can only do the verification half now.
1038 * We must wait for the secret to be entered
1039 * to continue. */
1040 char *question = (char *)tlv->data;
1041 char *qend = memchr(question, '\0', tlv->len - 1);
1042 size_t qlen = qend ? (qend - question + 1) : tlv->len;
1043 otrl_sm_step2a(context->smstate, tlv->data + qlen,
1044 tlv->len - qlen, 1);
1045 }
1046 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1);
1047 if (tlv && nextMsg == OTRL_SMP_EXPECT1) {
1048 /* We can only do the verification half now.
1049 * We must wait for the secret to be entered
1050 * to continue. */
1051 otrl_sm_step2a(context->smstate, tlv->data, tlv->len,
1052 0);
1053 }
1054 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2);
1055 if (tlv && nextMsg == OTRL_SMP_EXPECT2) {
1056 unsigned char* nextmsg;
1057 int nextmsglen;
1058 OtrlTLV *sendtlv;
1059 char *sendsmp;
1060 otrl_sm_step3(context->smstate, tlv->data, tlv->len,
1061 &nextmsg, &nextmsglen);
1062
1063 if (context->smstate->sm_prog_state !=
1064 OTRL_SMP_PROG_CHEATED) {
1065 /* Send msg with next smp msg content */
1066 sendtlv = otrl_tlv_new(OTRL_TLV_SMP3, nextmsglen,
1067 nextmsg);
1068 err = otrl_proto_create_data(&sendsmp,
1069 context, "", sendtlv,
1070 OTRL_MSGFLAGS_IGNORE_UNREADABLE);
1071 if (!err) {
1072 err = otrl_message_fragment_and_send(ops,
1073 opdata, context, sendsmp,
1074 OTRL_FRAGMENT_SEND_ALL, NULL);
1075 }
1076 free(sendsmp);
1077 otrl_tlv_free(sendtlv);
1078 }
1079 free(nextmsg);
1080 }
1081 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3);
1082 if (tlv && nextMsg == OTRL_SMP_EXPECT3) {
1083 unsigned char* nextmsg;
1084 int nextmsglen;
1085 OtrlTLV *sendtlv;
1086 char *sendsmp;
1087 err = otrl_sm_step4(context->smstate, tlv->data,
1088 tlv->len, &nextmsg, &nextmsglen);
1089 /* Set trust level based on result */
1090 if (context->smstate->received_question == 0) {
1091 set_smp_trust(ops, opdata, context,
1092 (err == gcry_error(GPG_ERR_NO_ERROR)));
1093 }
1094
1095 if (context->smstate->sm_prog_state !=
1096 OTRL_SMP_PROG_CHEATED) {
1097 /* Send msg with next smp msg content */
1098 sendtlv = otrl_tlv_new(OTRL_TLV_SMP4, nextmsglen,
1099 nextmsg);
1100 err = otrl_proto_create_data(&sendsmp,
1101 context, "", sendtlv,
1102 OTRL_MSGFLAGS_IGNORE_UNREADABLE);
1103 if (!err) {
1104 err = otrl_message_fragment_and_send(ops,
1105 opdata, context, sendsmp,
1106 OTRL_FRAGMENT_SEND_ALL, NULL);
1107 }
1108 free(sendsmp);
1109 otrl_tlv_free(sendtlv);
1110 }
1111 free(nextmsg);
1112 }
1113 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4);
1114 if (tlv && nextMsg == OTRL_SMP_EXPECT4) {
1115 err = otrl_sm_step5(context->smstate, tlv->data,
1116 tlv->len);
1117 /* Set trust level based on result */
1118 set_smp_trust(ops, opdata, context,
1119 (err == gcry_error(GPG_ERR_NO_ERROR)));
1120 }
1121 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT);
1122 if (tlv) {
1123 context->smstate->nextExpected = OTRL_SMP_EXPECT1;
1124 }
1125 if (plaintext[0] == '\0') {
1126 /* If it's a heartbeat (an empty message), don't
1127 * display it to the user, but log a debug message. */
1128 format = "Heartbeat received from %s.\n";
1129 buf = malloc(strlen(format) + strlen(sender) - 1);
1130 if (buf) {
1131 sprintf(buf, format, sender);
1132 if (ops->log_message) {
1133 ops->log_message(opdata, buf);
1134 }
1135 free(buf);
1136 }
1137 edata.ignore_message = 1;
1138 } else if (edata.ignore_message == 0 &&
1139 context->their_keyid > 0) {
1140 /* If it's *not* a heartbeat, and we haven't
1141 * sent anything in a while, also send a
1142 * heartbeat. */
1143 time_t now = time(NULL);
1144 if (context->lastsent < (now - HEARTBEAT_INTERVAL)) {
1145 char *heartbeat;
1146
1147 /* Create the heartbeat message */
1148 err = otrl_proto_create_data(&heartbeat,
1149 context, "", NULL,
1150 OTRL_MSGFLAGS_IGNORE_UNREADABLE);
1151 if (!err) {
1152 /* Send it, and log a debug message */
1153 if (ops->inject_message) {
1154 ops->inject_message(opdata, accountname,
1155 protocol, sender, heartbeat);
1156 }
1157 free(heartbeat);
1158
1159 context->lastsent = now;
1160
1161 /* Log a debug message */
1162 format = "Heartbeat sent to %s.\n";
1163 buf = malloc(strlen(format) + strlen(sender)
1164 - 1);
1165 if (buf) {
1166 sprintf(buf, format, sender);
1167 if (ops->log_message) {
1168 ops->log_message(opdata, buf);
1169 }
1170 free(buf);
1171 }
1172 }
1173 }
1174 }
1175
1176 /* Return the TLVs even if ignore_message == 1 so
1177 * that we can attach TLVs to heartbeats. */
1178 if (tlvsp) {
1179 *tlvsp = tlvs;
1180 } else {
1181 otrl_tlv_free(tlvs);
1182 }
1183
1184 if (edata.ignore_message != 1) {
1185 *newmessagep = plaintext;
1186 edata.ignore_message = 0;
1187 } else {
1188 free(plaintext);
1189 }
1190 break;
1191 }
1192 break;
1193
1194 case OTRL_MSGTYPE_ERROR:
1195 if ((policy & OTRL_POLICY_ERROR_START_AKE)) {
1196 char *msgtosend = otrl_proto_default_query_msg(
1197 context->accountname, policy);
1198 if (msgtosend && ops->inject_message) {
1199 ops->inject_message(opdata, context->accountname,
1200 context->protocol, context->username,
1201 msgtosend);
1202 }
1203 free(msgtosend);
1204 }
1205
1206 if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
1207 /* Mark the last message we sent as eligible for
1208 * retransmission */
1209 context->may_retransmit = 1;
1210 }
1211
1212 /* In any event, display the error message, with the
1213 * display_otr_message callback, if possible */
1214 if (ops->display_otr_message) {
1215 const char *otrerror = strstr(message, "?OTR Error:");
1216 if (otrerror) {
1217 /* Skip the leading '?' */
1218 ++otrerror;
1219 } else {
1220 otrerror = message;
1221 }
1222 if (!ops->display_otr_message(opdata, accountname, protocol,
1223 sender, otrerror)) {
1224 edata.ignore_message = 1;
1225 }
1226 }
1227 break;
1228
1229 case OTRL_MSGTYPE_TAGGEDPLAINTEXT:
1230 /* Strip the tag from the message */
1231 bestversion = otrl_proto_whitespace_bestversion(message,
1232 &startwhite, &endwhite, policy);
1233 if (startwhite && endwhite) {
1234 size_t restlen = strlen(endwhite);
1235 char *strippedmsg = strdup(message);
1236
1237 if (strippedmsg) {
1238 memmove(strippedmsg + (startwhite - message),
1239 strippedmsg + (endwhite - message), restlen+1);
1240 *newmessagep = strippedmsg;
1241 edata.ignore_message = 0;
1242 }
1243 }
1244 if (bestversion && context->msgstate != OTRL_MSGSTATE_ENCRYPTED
1245 && (policy & OTRL_POLICY_WHITESPACE_START_AKE)) {
1246 switch(bestversion) {
1247 case 2:
1248 err = otrl_auth_start_v2(&(context->auth));
1249 send_or_error_auth(ops, opdata, err, context);
1250 break;
1251 case 1:
1252 /* Get our private key */
1253 privkey = otrl_privkey_find(us, context->accountname,
1254 context->protocol);
1255 if (privkey == NULL) {
1256 /* We've got no private key! */
1257 if (ops->create_privkey) {
1258 ops->create_privkey(opdata,
1259 context->accountname,
1260 context->protocol);
1261 privkey = otrl_privkey_find(us,
1262 context->accountname,
1263 context->protocol);
1264 }
1265 }
1266 if (privkey) {
1267 err = otrl_auth_start_v1(&(context->auth), NULL, 0,
1268 privkey);
1269 send_or_error_auth(ops, opdata, err, context);
1270 }
1271 break;
1272 default:
1273 /* Don't start the AKE */
1274 break;
1275 }
1276 }
1277
1278 /* FALLTHROUGH */
1279 case OTRL_MSGTYPE_NOTOTR:
1280 if (context->msgstate != OTRL_MSGSTATE_PLAINTEXT ||
1281 (policy & OTRL_POLICY_REQUIRE_ENCRYPTION)) {
1282 /* Not fine. Let the user know. */
1283
1284 /* Don't use g_strdup_printf here, because someone
1285 * (not us) is going to free() the *message pointer,
1286 * not g_free() it. */
1287 const char *plainmsg = (*newmessagep) ? *newmessagep : message;
1288 const char *format = "NOT encrypted: [%s]";
1289 char *buf = 0;
1290 if (policy & OTRL_POLICY_REQUIRE_ENCRYPTION) {
1291 format = "%s sent a message that was NOT encrypted.";
1292 buf = malloc(strlen(format) + strlen(context->username)
1293 + strlen(plainmsg) - 1);
1294 /* Remove "%s", add username + message + '\0' */
1295 }
1296 else
1297 {
1298 buf = malloc(strlen(format) + strlen(context->username)
1299 + strlen(plainmsg) - 3);
1300 /* Remove "%s%s", add username + message + '\0' */
1301 }
1302 if (buf) {
1303 sprintf(buf, format, plainmsg);
1304 if (ops->display_otr_message) {
1305 if (!ops->display_otr_message(opdata, accountname,
1306 protocol, sender, buf)) {
1307 free(*newmessagep);
1308 *newmessagep = NULL;
1309 edata.ignore_message = 1;
1310 }
1311 }
1312 if (edata.ignore_message != 1) {
1313 free(*newmessagep);
1314 *newmessagep = buf;
1315 edata.ignore_message = 0;
1316 } else {
1317 free(buf);
1318 }
1319 }
1320 }
1321 break;
1322
1323 case OTRL_MSGTYPE_UNKNOWN:
1324 /* We received an OTR message we didn't recognize. Ignore
1325 * it, but make a log entry. */
1326 if (ops->log_message) {
1327 const char *format = "Unrecognized OTR message received "
1328 "from %s.\n";
1329 char *buf = malloc(strlen(format) + strlen(sender) - 1);
1330 if (buf) {
1331 sprintf(buf, format, sender);
1332 ops->log_message(opdata, buf);
1333 free(buf);
1334 }
1335 }
1336 if (edata.ignore_message == -1) edata.ignore_message = 1;
1337 break;
1338 }
1339
1340 /* If we reassembled a fragmented message, we need to free the
1341 * allocated memory now. */
1342 if (fragment_assembled) {
1343 free(unfragmessage);
1344 }
1345
1346 if (edata.ignore_message == -1) edata.ignore_message = 0;
1347 return edata.ignore_message;
1348}
1349
1350/* Send a message to the network, fragmenting first if necessary.
1351 * All messages to be sent to the network should go through this
1352 * method immediately before they are sent, ie after encryption. */
1353gcry_error_t otrl_message_fragment_and_send(const OtrlMessageAppOps *ops,
1354 void *opdata, ConnContext *context, const char *message,
1355 OtrlFragmentPolicy fragPolicy, char **returnFragment)
1356{
1357 int mms = 0;
1358 if (message && ops->inject_message) {
1359 int msglen;
1360
1361 if (otrl_api_version >= 0x030100 && ops->max_message_size) {
1362 mms = ops->max_message_size(opdata, context);
1363 }
1364 msglen = strlen(message);
1365
1366 /* Don't incur overhead of fragmentation unless necessary */
1367 if(mms != 0 && msglen > mms) {
1368 char **fragments;
1369 gcry_error_t err;
1370 int i;
1371 int fragment_count = ((msglen - 1) / (mms -19)) + 1;
1372 /* like ceil(msglen/(mms - 19)) */
1373
1374 err = otrl_proto_fragment_create(mms, fragment_count, &fragments,
1375 message);
1376 if (err) {
1377 return err;
1378 }
1379
1380 /* Determine which fragments to send and which to return
1381 * based on given Fragment Policy. If the first fragment
1382 * should be returned instead of sent, store it. */
1383 if (fragPolicy == OTRL_FRAGMENT_SEND_ALL_BUT_FIRST) {
1384 *returnFragment = strdup(fragments[0]);
1385 } else {
1386 ops->inject_message(opdata, context->accountname,
1387 context->protocol, context->username, fragments[0]);
1388 }
1389 for (i=1; i<fragment_count-1; i++) {
1390 ops->inject_message(opdata, context->accountname,
1391 context->protocol, context->username, fragments[i]);
1392 }
1393 /* If the last fragment should be stored instead of sent,
1394 * store it */
1395 if (fragPolicy == OTRL_FRAGMENT_SEND_ALL_BUT_LAST) {
1396 *returnFragment = strdup(fragments[fragment_count-1]);
1397 } else {
1398 ops->inject_message(opdata, context->accountname,
1399 context->protocol, context->username, fragments[fragment_count-1]);
1400 }
1401 /* Now free all fragment memory */
1402 otrl_proto_fragment_free(&fragments, fragment_count);
1403
1404 } else {
1405 /* No fragmentation necessary */
1406 if (fragPolicy == OTRL_FRAGMENT_SEND_ALL) {
1407 ops->inject_message(opdata, context->accountname,
1408 context->protocol, context->username, message);
1409 } else {
1410 /* Copy and return the entire given message. */
1411 int l = strlen(message) + 1;
1412 *returnFragment = malloc(sizeof(char)*l);
1413 strcpy(*returnFragment, message);
1414 }
1415 }
1416 }
1417 return gcry_error(GPG_ERR_NO_ERROR);
1418}
1419
1420/* Put a connection into the PLAINTEXT state, first sending the
1421 * other side a notice that we're doing so if we're currently ENCRYPTED,
1422 * and we think he's logged in. */
1423void otrl_message_disconnect(OtrlUserState us, const OtrlMessageAppOps *ops,
1424 void *opdata, const char *accountname, const char *protocol,
1425 const char *username)
1426{
1427 ConnContext *context = otrl_context_find(us, username, accountname,
1428 protocol, 0, NULL, NULL, NULL);
1429
1430 if (!context) return;
1431
1432 if (context->msgstate == OTRL_MSGSTATE_ENCRYPTED &&
1433 context->their_keyid > 0 &&
1434 ops->is_logged_in &&
1435 ops->is_logged_in(opdata, accountname, protocol, username) == 1) {
1436 if (ops->inject_message) {
1437 char *encmsg = NULL;
1438 gcry_error_t err;
1439 OtrlTLV *tlv = otrl_tlv_new(OTRL_TLV_DISCONNECTED, 0, NULL);
1440
1441 err = otrl_proto_create_data(&encmsg, context, "", tlv,
1442 OTRL_MSGFLAGS_IGNORE_UNREADABLE);
1443 if (!err) {
1444 ops->inject_message(opdata, accountname, protocol,
1445 username, encmsg);
1446 }
1447 free(encmsg);
1448 }
1449 }
1450
1451 otrl_context_force_plaintext(context);
1452 if (ops->update_context_list) {
1453 ops->update_context_list(opdata);
1454 }
1455}
diff --git a/linden/indra/libotr/libotr-3.2.0/src/message.h b/linden/indra/libotr/libotr-3.2.0/src/message.h
new file mode 100755
index 0000000..e658e9d
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/message.h
@@ -0,0 +1,210 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef __MESSAGE_H__
21#define __MESSAGE_H__
22
23typedef enum {
24 OTRL_NOTIFY_ERROR,
25 OTRL_NOTIFY_WARNING,
26 OTRL_NOTIFY_INFO
27} OtrlNotifyLevel;
28
29typedef struct s_OtrlMessageAppOps {
30 /* Return the OTR policy for the given context. */
31 OtrlPolicy (*policy)(void *opdata, ConnContext *context);
32
33 /* Create a private key for the given accountname/protocol if
34 * desired. */
35 void (*create_privkey)(void *opdata, const char *accountname,
36 const char *protocol);
37
38 /* Report whether you think the given user is online. Return 1 if
39 * you think he is, 0 if you think he isn't, -1 if you're not sure.
40 *
41 * If you return 1, messages such as heartbeats or other
42 * notifications may be sent to the user, which could result in "not
43 * logged in" errors if you're wrong. */
44 int (*is_logged_in)(void *opdata, const char *accountname,
45 const char *protocol, const char *recipient);
46
47 /* Send the given IM to the given recipient from the given
48 * accountname/protocol. */
49 void (*inject_message)(void *opdata, const char *accountname,
50 const char *protocol, const char *recipient, const char *message);
51
52 /* Display a notification message for a particular accountname /
53 * protocol / username conversation. */
54 void (*notify)(void *opdata, OtrlNotifyLevel level,
55 const char *accountname, const char *protocol,
56 const char *username, const char *title,
57 const char *primary, const char *secondary);
58
59 /* Display an OTR control message for a particular accountname /
60 * protocol / username conversation. Return 0 if you are able to
61 * successfully display it. If you return non-0 (or if this
62 * function is NULL), the control message will be displayed inline,
63 * as a received message, or else by using the above notify()
64 * callback. */
65 int (*display_otr_message)(void *opdata, const char *accountname,
66 const char *protocol, const char *username, const char *msg);
67
68 /* When the list of ConnContexts changes (including a change in
69 * state), this is called so the UI can be updated. */
70 void (*update_context_list)(void *opdata);
71
72 /* Return a newly allocated string containing a human-friendly name
73 * for the given protocol id */
74 const char *(*protocol_name)(void *opdata, const char *protocol);
75
76 /* Deallocate a string allocated by protocol_name */
77 void (*protocol_name_free)(void *opdata, const char *protocol_name);
78
79 /* A new fingerprint for the given user has been received. */
80 void (*new_fingerprint)(void *opdata, OtrlUserState us,
81 const char *accountname, const char *protocol,
82 const char *username, unsigned char fingerprint[20]);
83
84 /* The list of known fingerprints has changed. Write them to disk. */
85 void (*write_fingerprints)(void *opdata);
86
87 /* A ConnContext has entered a secure state. */
88 void (*gone_secure)(void *opdata, ConnContext *context);
89
90 /* A ConnContext has left a secure state. */
91 void (*gone_insecure)(void *opdata, ConnContext *context);
92
93 /* We have completed an authentication, using the D-H keys we
94 * already knew. is_reply indicates whether we initiated the AKE. */
95 void (*still_secure)(void *opdata, ConnContext *context, int is_reply);
96
97 /* Log a message. The passed message will end in "\n". */
98 void (*log_message)(void *opdata, const char *message);
99
100 /* Find the maximum message size supported by this protocol. */
101 int (*max_message_size)(void *opdata, ConnContext *context);
102
103 /* Return a newly allocated string containing a human-friendly
104 * representation for the given account */
105 const char *(*account_name)(void *opdata, const char *account,
106 const char *protocol);
107
108 /* Deallocate a string returned by account_name */
109 void (*account_name_free)(void *opdata, const char *account_name);
110
111} OtrlMessageAppOps;
112
113/* Deallocate a message allocated by other otrl_message_* routines. */
114void otrl_message_free(char *message);
115
116/* Handle a message about to be sent to the network. It is safe to pass
117 * all messages about to be sent to this routine. add_appdata is a
118 * function that will be called in the event that a new ConnContext is
119 * created. It will be passed the data that you supplied, as well as a
120 * pointer to the new ConnContext. You can use this to add
121 * application-specific information to the ConnContext using the
122 * "context->app" field, for example. If you don't need to do this, you
123 * can pass NULL for the last two arguments of otrl_message_sending.
124 *
125 * tlvs is a chain of OtrlTLVs to append to the private message. It is
126 * usually correct to just pass NULL here.
127 *
128 * If this routine returns non-zero, then the library tried to encrypt
129 * the message, but for some reason failed. DO NOT send the message in
130 * the clear in that case.
131 *
132 * If *messagep gets set by the call to something non-NULL, then you
133 * should replace your message with the contents of *messagep, and
134 * send that instead. Call otrl_message_free(*messagep) when you're
135 * done with it. */
136gcry_error_t otrl_message_sending(OtrlUserState us,
137 const OtrlMessageAppOps *ops,
138 void *opdata, const char *accountname, const char *protocol,
139 const char *recipient, const char *message, OtrlTLV *tlvs,
140 char **messagep,
141 void (*add_appdata)(void *data, ConnContext *context),
142 void *data);
143
144/* Handle a message just received from the network. It is safe to pass
145 * all received messages to this routine. add_appdata is a function
146 * that will be called in the event that a new ConnContext is created.
147 * It will be passed the data that you supplied, as well as
148 * a pointer to the new ConnContext. You can use this to add
149 * application-specific information to the ConnContext using the
150 * "context->app" field, for example. If you don't need to do this, you
151 * can pass NULL for the last two arguments of otrl_message_receiving.
152 *
153 * If otrl_message_receiving returns 1, then the message you received
154 * was an internal protocol message, and no message should be delivered
155 * to the user.
156 *
157 * If it returns 0, then check if *messagep was set to non-NULL. If
158 * so, replace the received message with the contents of *messagep, and
159 * deliver that to the user instead. You must call
160 * otrl_message_free(*messagep) when you're done with it. If tlvsp is
161 * non-NULL, *tlvsp will be set to a chain of any TLVs that were
162 * transmitted along with this message. You must call
163 * otrl_tlv_free(*tlvsp) when you're done with those.
164 *
165 * If otrl_message_receiving returns 0 and *messagep is NULL, then this
166 * was an ordinary, non-OTR message, which should just be delivered to
167 * the user without modification. */
168int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops,
169 void *opdata, const char *accountname, const char *protocol,
170 const char *sender, const char *message, char **newmessagep,
171 OtrlTLV **tlvsp,
172 void (*add_appdata)(void *data, ConnContext *context),
173 void *data);
174
175/* Send a message to the network, fragmenting first if necessary.
176 * All messages to be sent to the network should go through this
177 * method immediately before they are sent, ie after encryption. */
178gcry_error_t otrl_message_fragment_and_send(const OtrlMessageAppOps *ops,
179 void *opdata, ConnContext *context, const char *message,
180 OtrlFragmentPolicy fragPolicy, char **returnFragment);
181
182/* Put a connection into the PLAINTEXT state, first sending the
183 * other side a notice that we're doing so if we're currently ENCRYPTED,
184 * and we think he's logged in. */
185void otrl_message_disconnect(OtrlUserState us, const OtrlMessageAppOps *ops,
186 void *opdata, const char *accountname, const char *protocol,
187 const char *username);
188
189/* Initiate the Socialist Millionaires' Protocol */
190void otrl_message_initiate_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
191 void *opdata, ConnContext *context, const unsigned char *secret,
192 size_t secretlen);
193
194/* Initiate the Socialist Millionaires' Protocol and send a prompt
195 * question to the buddy */
196void otrl_message_initiate_smp_q(OtrlUserState us,
197 const OtrlMessageAppOps *ops, void *opdata, ConnContext *context,
198 const char *question, const unsigned char *secret, size_t secretlen);
199
200/* Respond to a buddy initiating the Socialist Millionaires' Protocol */
201void otrl_message_respond_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
202 void *opdata, ConnContext *context, const unsigned char *secret,
203 size_t secretlen);
204
205/* Abort the SMP. Called when an unexpected SMP message breaks the
206 * normal flow. */
207void otrl_message_abort_smp(OtrlUserState us, const OtrlMessageAppOps *ops,
208 void *opdata, ConnContext *context);
209
210#endif
diff --git a/linden/indra/libotr/libotr-3.2.0/src/privkey-t.h b/linden/indra/libotr/libotr-3.2.0/src/privkey-t.h
new file mode 100755
index 0000000..3421b8b
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/privkey-t.h
@@ -0,0 +1,39 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef __PRIVKEY_T_H__
21#define __PRIVKEY_T_H__
22
23#include <gcrypt.h>
24
25typedef struct s_OtrlPrivKey {
26 struct s_OtrlPrivKey *next;
27 struct s_OtrlPrivKey **tous;
28
29 char *accountname;
30 char *protocol;
31 unsigned short pubkey_type;
32 gcry_sexp_t privkey;
33 unsigned char *pubkey_data;
34 size_t pubkey_datalen;
35} OtrlPrivKey;
36
37#define OTRL_PUBKEY_TYPE_DSA 0x0000
38
39#endif
diff --git a/linden/indra/libotr/libotr-3.2.0/src/privkey.c b/linden/indra/libotr/libotr-3.2.0/src/privkey.c
new file mode 100755
index 0000000..aacecd5
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/privkey.c
@@ -0,0 +1,745 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/* system headers */
21#include <stdio.h>
22#include <stdlib.h>
23#include <errno.h>
24#include <sys/stat.h>
25
26/* libgcrypt headers */
27#include <gcrypt.h>
28
29/* libotr headers */
30#include "privkey.h"
31#include "serial.h"
32
33/* Convert a 20-byte hash value to a 45-byte human-readable value */
34void otrl_privkey_hash_to_human(char human[45], const unsigned char hash[20])
35{
36 int word, byte;
37 char *p = human;
38
39 for(word=0; word<5; ++word) {
40 for(byte=0; byte<4; ++byte) {
41 sprintf(p, "%02X", hash[word*4+byte]);
42 p += 2;
43 }
44 *(p++) = ' ';
45 }
46 /* Change that last ' ' to a '\0' */
47 --p;
48 *p = '\0';
49}
50
51/* Calculate a human-readable hash of our DSA public key. Return it in
52 * the passed fingerprint buffer. Return NULL on error, or a pointer to
53 * the given buffer on success. */
54char *otrl_privkey_fingerprint(OtrlUserState us, char fingerprint[45],
55 const char *accountname, const char *protocol)
56{
57 unsigned char hash[20];
58 OtrlPrivKey *p = otrl_privkey_find(us, accountname, protocol);
59
60 if (p) {
61 /* Calculate the hash */
62 gcry_md_hash_buffer(GCRY_MD_SHA1, hash, p->pubkey_data,
63 p->pubkey_datalen);
64
65 /* Now convert it to a human-readable format */
66 otrl_privkey_hash_to_human(fingerprint, hash);
67 } else {
68 return NULL;
69 }
70
71 return fingerprint;
72}
73
74/* Calculate a raw hash of our DSA public key. Return it in the passed
75 * fingerprint buffer. Return NULL on error, or a pointer to the given
76 * buffer on success. */
77unsigned char *otrl_privkey_fingerprint_raw(OtrlUserState us,
78 unsigned char hash[20], const char *accountname, const char *protocol)
79{
80 OtrlPrivKey *p = otrl_privkey_find(us, accountname, protocol);
81
82 if (p) {
83 /* Calculate the hash */
84 gcry_md_hash_buffer(GCRY_MD_SHA1, hash, p->pubkey_data,
85 p->pubkey_datalen);
86 } else {
87 return NULL;
88 }
89
90 return hash;
91}
92
93/* Create a public key block from a private key */
94static gcry_error_t make_pubkey(unsigned char **pubbufp, size_t *publenp,
95 gcry_sexp_t privkey)
96{
97 gcry_mpi_t p,q,g,y;
98 gcry_sexp_t dsas,ps,qs,gs,ys;
99 size_t np,nq,ng,ny;
100 enum gcry_mpi_format format = GCRYMPI_FMT_USG;
101 unsigned char *bufp;
102 size_t lenp;
103
104 *pubbufp = NULL;
105 *publenp = 0;
106
107 /* Extract the public parameters */
108 dsas = gcry_sexp_find_token(privkey, "dsa", 0);
109 if (dsas == NULL) {
110 return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
111 }
112 ps = gcry_sexp_find_token(dsas, "p", 0);
113 qs = gcry_sexp_find_token(dsas, "q", 0);
114 gs = gcry_sexp_find_token(dsas, "g", 0);
115 ys = gcry_sexp_find_token(dsas, "y", 0);
116 gcry_sexp_release(dsas);
117 if (!ps || !qs || !gs || !ys) {
118 gcry_sexp_release(ps);
119 gcry_sexp_release(qs);
120 gcry_sexp_release(gs);
121 gcry_sexp_release(ys);
122 return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
123 }
124 p = gcry_sexp_nth_mpi(ps, 1, GCRYMPI_FMT_USG);
125 gcry_sexp_release(ps);
126 q = gcry_sexp_nth_mpi(qs, 1, GCRYMPI_FMT_USG);
127 gcry_sexp_release(qs);
128 g = gcry_sexp_nth_mpi(gs, 1, GCRYMPI_FMT_USG);
129 gcry_sexp_release(gs);
130 y = gcry_sexp_nth_mpi(ys, 1, GCRYMPI_FMT_USG);
131 gcry_sexp_release(ys);
132 if (!p || !q || !g || !y) {
133 gcry_mpi_release(p);
134 gcry_mpi_release(q);
135 gcry_mpi_release(g);
136 gcry_mpi_release(y);
137 return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
138 }
139
140 *publenp = 0;
141 gcry_mpi_print(format, NULL, 0, &np, p);
142 *publenp += np + 4;
143 gcry_mpi_print(format, NULL, 0, &nq, q);
144 *publenp += nq + 4;
145 gcry_mpi_print(format, NULL, 0, &ng, g);
146 *publenp += ng + 4;
147 gcry_mpi_print(format, NULL, 0, &ny, y);
148 *publenp += ny + 4;
149
150 *pubbufp = malloc(*publenp);
151 if (*pubbufp == NULL) {
152 gcry_mpi_release(p);
153 gcry_mpi_release(q);
154 gcry_mpi_release(g);
155 gcry_mpi_release(y);
156 return gcry_error(GPG_ERR_ENOMEM);
157 }
158 bufp = *pubbufp;
159 lenp = *publenp;
160
161 write_mpi(p,np,"P");
162 write_mpi(q,nq,"Q");
163 write_mpi(g,ng,"G");
164 write_mpi(y,ny,"Y");
165
166 gcry_mpi_release(p);
167 gcry_mpi_release(q);
168 gcry_mpi_release(g);
169 gcry_mpi_release(y);
170
171 return gcry_error(GPG_ERR_NO_ERROR);
172}
173
174/* Read a sets of private DSA keys from a file on disk into the given
175 * OtrlUserState. */
176gcry_error_t otrl_privkey_read(OtrlUserState us, const char *filename)
177{
178 FILE *privf;
179 gcry_error_t err;
180
181 /* Open the privkey file. We use rb mode so that on WIN32, fread()
182 * reads the same number of bytes that fstat() indicates are in the
183 * file. */
184 privf = fopen(filename, "rb");
185 if (!privf) {
186 err = gcry_error_from_errno(errno);
187 return err;
188 }
189
190 err = otrl_privkey_read_FILEp(us, privf);
191
192 fclose(privf);
193 return err;
194}
195
196/* Read a sets of private DSA keys from a FILE* into the given
197 * OtrlUserState. The FILE* must be open for reading. */
198gcry_error_t otrl_privkey_read_FILEp(OtrlUserState us, FILE *privf)
199{
200 int privfd;
201 struct stat st;
202 char *buf;
203 const char *token;
204 size_t tokenlen;
205 gcry_error_t err;
206 gcry_sexp_t allkeys;
207 size_t i;
208
209 if (!privf) return gcry_error(GPG_ERR_NO_ERROR);
210
211 /* Release any old ideas we had about our keys */
212 otrl_privkey_forget_all(us);
213
214 /* Load the data into a buffer */
215 privfd = fileno(privf);
216 if (fstat(privfd, &st)) {
217 err = gcry_error_from_errno(errno);
218 return err;
219 }
220 buf = malloc(st.st_size);
221 if (!buf && st.st_size > 0) {
222 return gcry_error(GPG_ERR_ENOMEM);
223 }
224 if (fread(buf, st.st_size, 1, privf) != 1) {
225 err = gcry_error_from_errno(errno);
226 free(buf);
227 return err;
228 }
229
230 err = gcry_sexp_new(&allkeys, buf, st.st_size, 0);
231 free(buf);
232 if (err) {
233 return err;
234 }
235
236 token = gcry_sexp_nth_data(allkeys, 0, &tokenlen);
237 if (tokenlen != 8 || strncmp(token, "privkeys", 8)) {
238 gcry_sexp_release(allkeys);
239 return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
240 }
241
242 /* Get each account */
243 for(i=1; i<((size_t)gcry_sexp_length(allkeys)); ++i) {
244 gcry_sexp_t names, protos, privs;
245 char *name, *proto;
246 gcry_sexp_t accounts;
247 OtrlPrivKey *p;
248
249 /* Get the ith "account" S-exp */
250 accounts = gcry_sexp_nth(allkeys, i);
251
252 /* It's really an "account" S-exp? */
253 token = gcry_sexp_nth_data(accounts, 0, &tokenlen);
254 if (tokenlen != 7 || strncmp(token, "account", 7)) {
255 gcry_sexp_release(accounts);
256 gcry_sexp_release(allkeys);
257 return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
258 }
259 /* Extract the name, protocol, and privkey S-exps */
260 names = gcry_sexp_find_token(accounts, "name", 0);
261 protos = gcry_sexp_find_token(accounts, "protocol", 0);
262 privs = gcry_sexp_find_token(accounts, "private-key", 0);
263 gcry_sexp_release(accounts);
264 if (!names || !protos || !privs) {
265 gcry_sexp_release(names);
266 gcry_sexp_release(protos);
267 gcry_sexp_release(privs);
268 gcry_sexp_release(allkeys);
269 return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
270 }
271 /* Extract the actual name and protocol */
272 token = gcry_sexp_nth_data(names, 1, &tokenlen);
273 if (!token) {
274 gcry_sexp_release(names);
275 gcry_sexp_release(protos);
276 gcry_sexp_release(privs);
277 gcry_sexp_release(allkeys);
278 return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
279 }
280 name = malloc(tokenlen + 1);
281 if (!name) {
282 gcry_sexp_release(names);
283 gcry_sexp_release(protos);
284 gcry_sexp_release(privs);
285 gcry_sexp_release(allkeys);
286 return gcry_error(GPG_ERR_ENOMEM);
287 }
288 memmove(name, token, tokenlen);
289 name[tokenlen] = '\0';
290 gcry_sexp_release(names);
291
292 token = gcry_sexp_nth_data(protos, 1, &tokenlen);
293 if (!token) {
294 free(name);
295 gcry_sexp_release(protos);
296 gcry_sexp_release(privs);
297 gcry_sexp_release(allkeys);
298 return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
299 }
300 proto = malloc(tokenlen + 1);
301 if (!proto) {
302 free(name);
303 gcry_sexp_release(protos);
304 gcry_sexp_release(privs);
305 gcry_sexp_release(allkeys);
306 return gcry_error(GPG_ERR_ENOMEM);
307 }
308 memmove(proto, token, tokenlen);
309 proto[tokenlen] = '\0';
310 gcry_sexp_release(protos);
311
312 /* Make a new OtrlPrivKey entry */
313 p = malloc(sizeof(*p));
314 if (!p) {
315 free(name);
316 free(proto);
317 gcry_sexp_release(privs);
318 gcry_sexp_release(allkeys);
319 return gcry_error(GPG_ERR_ENOMEM);
320 }
321
322 /* Fill it in and link it up */
323 p->accountname = name;
324 p->protocol = proto;
325 p->pubkey_type = OTRL_PUBKEY_TYPE_DSA;
326 p->privkey = privs;
327 p->next = us->privkey_root;
328 if (p->next) {
329 p->next->tous = &(p->next);
330 }
331 p->tous = &(us->privkey_root);
332 us->privkey_root = p;
333 err = make_pubkey(&(p->pubkey_data), &(p->pubkey_datalen), p->privkey);
334 if (err) {
335 gcry_sexp_release(allkeys);
336 otrl_privkey_forget(p);
337 return gcry_error(GPG_ERR_UNUSABLE_SECKEY);
338 }
339 }
340 gcry_sexp_release(allkeys);
341
342 return gcry_error(GPG_ERR_NO_ERROR);
343}
344
345static gcry_error_t sexp_write(FILE *privf, gcry_sexp_t sexp)
346{
347 size_t buflen;
348 char *buf;
349
350 buflen = gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
351 buf = malloc(buflen);
352 if (buf == NULL && buflen > 0) {
353 return gcry_error(GPG_ERR_ENOMEM);
354 }
355 gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, buf, buflen);
356
357 fprintf(privf, "%s", buf);
358 free(buf);
359
360 return gcry_error(GPG_ERR_NO_ERROR);
361}
362
363static gcry_error_t account_write(FILE *privf, const char *accountname,
364 const char *protocol, gcry_sexp_t privkey)
365{
366 gcry_error_t err;
367 gcry_sexp_t names, protos;
368
369 fprintf(privf, " (account\n");
370
371 err = gcry_sexp_build(&names, NULL, "(name %s)", accountname);
372 if (!err) {
373 err = sexp_write(privf, names);
374 gcry_sexp_release(names);
375 }
376 if (!err) err = gcry_sexp_build(&protos, NULL, "(protocol %s)", protocol);
377 if (!err) {
378 err = sexp_write(privf, protos);
379 gcry_sexp_release(protos);
380 }
381 if (!err) err = sexp_write(privf, privkey);
382
383 fprintf(privf, " )\n");
384
385 return err;
386}
387
388/* Generate a private DSA key for a given account, storing it into a
389 * file on disk, and loading it into the given OtrlUserState. Overwrite any
390 * previously generated keys for that account in that OtrlUserState. */
391gcry_error_t otrl_privkey_generate(OtrlUserState us, const char *filename,
392 const char *accountname, const char *protocol)
393{
394 gcry_error_t err;
395 FILE *privf;
396#ifndef WIN32
397 mode_t oldmask;
398#endif
399
400#ifndef WIN32
401 oldmask = umask(077);
402#endif
403 privf = fopen(filename, "w+b");
404 if (!privf) {
405#ifndef WIN32
406 umask(oldmask);
407#endif
408 err = gcry_error_from_errno(errno);
409 return err;
410 }
411
412 err = otrl_privkey_generate_FILEp(us, privf, accountname, protocol);
413
414 fclose(privf);
415#ifndef WIN32
416 umask(oldmask);
417#endif
418 return err;
419}
420
421/* Generate a private DSA key for a given account, storing it into a
422 * FILE*, and loading it into the given OtrlUserState. Overwrite any
423 * previously generated keys for that account in that OtrlUserState.
424 * The FILE* must be open for reading and writing. */
425gcry_error_t otrl_privkey_generate_FILEp(OtrlUserState us, FILE *privf,
426 const char *accountname, const char *protocol)
427{
428 gcry_error_t err;
429 gcry_sexp_t key, parms, privkey;
430 static const char *parmstr = "(genkey (dsa (nbits 4:1024)))";
431 OtrlPrivKey *p;
432
433 if (!privf) return gcry_error(GPG_ERR_NO_ERROR);
434
435 /* Create a DSA key */
436 err = gcry_sexp_new(&parms, parmstr, strlen(parmstr), 0);
437 if (err) {
438 return err;
439 }
440 err = gcry_pk_genkey(&key, parms);
441 gcry_sexp_release(parms);
442 if (err) {
443 return err;
444 }
445
446 /* Extract the privkey */
447 privkey = gcry_sexp_find_token(key, "private-key", 0);
448 gcry_sexp_release(key);
449
450 /* Output the other keys we know */
451 fprintf(privf, "(privkeys\n");
452
453 for (p=us->privkey_root; p; p=p->next) {
454 /* Skip this one if our new key replaces it */
455 if (!strcmp(p->accountname, accountname) &&
456 !strcmp(p->protocol, protocol)) {
457 continue;
458 }
459
460 account_write(privf, p->accountname, p->protocol, p->privkey);
461 }
462 account_write(privf, accountname, protocol, privkey);
463 gcry_sexp_release(privkey);
464 fprintf(privf, ")\n");
465
466 fseek(privf, 0, SEEK_SET);
467
468 return otrl_privkey_read_FILEp(us, privf);
469}
470
471/* Convert a hex character to a value */
472static unsigned int ctoh(char c)
473{
474 if (c >= '0' && c <= '9') return c-'0';
475 if (c >= 'a' && c <= 'f') return c-'a'+10;
476 if (c >= 'A' && c <= 'F') return c-'A'+10;
477 return 0; /* Unknown hex char */
478}
479
480/* Read the fingerprint store from a file on disk into the given
481 * OtrlUserState. Use add_app_data to add application data to each
482 * ConnContext so created. */
483gcry_error_t otrl_privkey_read_fingerprints(OtrlUserState us,
484 const char *filename,
485 void (*add_app_data)(void *data, ConnContext *context),
486 void *data)
487{
488 gcry_error_t err;
489 FILE *storef;
490
491 storef = fopen(filename, "rb");
492 if (!storef) {
493 err = gcry_error_from_errno(errno);
494 return err;
495 }
496
497 err = otrl_privkey_read_fingerprints_FILEp(us, storef, add_app_data, data);
498
499 fclose(storef);
500 return err;
501}
502
503/* Read the fingerprint store from a FILE* into the given
504 * OtrlUserState. Use add_app_data to add application data to each
505 * ConnContext so created. The FILE* must be open for reading. */
506gcry_error_t otrl_privkey_read_fingerprints_FILEp(OtrlUserState us,
507 FILE *storef,
508 void (*add_app_data)(void *data, ConnContext *context),
509 void *data)
510{
511 ConnContext *context;
512 char storeline[1000];
513 unsigned char fingerprint[20];
514 size_t maxsize = sizeof(storeline);
515
516 if (!storef) return gcry_error(GPG_ERR_NO_ERROR);
517
518 while(fgets(storeline, maxsize, storef)) {
519 char *username;
520 char *accountname;
521 char *protocol;
522 char *hex;
523 char *trust;
524 char *tab;
525 char *eol;
526 Fingerprint *fng;
527 int i, j;
528 /* Parse the line, which should be of the form:
529 * username\taccountname\tprotocol\t40_hex_nybbles\n */
530 username = storeline;
531 tab = strchr(username, '\t');
532 if (!tab) continue;
533 *tab = '\0';
534
535 accountname = tab + 1;
536 tab = strchr(accountname, '\t');
537 if (!tab) continue;
538 *tab = '\0';
539
540 protocol = tab + 1;
541 tab = strchr(protocol, '\t');
542 if (!tab) continue;
543 *tab = '\0';
544
545 hex = tab + 1;
546 tab = strchr(hex, '\t');
547 if (!tab) {
548 eol = strchr(hex, '\r');
549 if (!eol) eol = strchr(hex, '\n');
550 if (!eol) continue;
551 *eol = '\0';
552 trust = NULL;
553 } else {
554 *tab = '\0';
555 trust = tab + 1;
556 eol = strchr(trust, '\r');
557 if (!eol) eol = strchr(trust, '\n');
558 if (!eol) continue;
559 *eol = '\0';
560 }
561
562 if (strlen(hex) != 40) continue;
563 for(j=0, i=0; i<40; i+=2) {
564 fingerprint[j++] = (ctoh(hex[i]) << 4) + (ctoh(hex[i+1]));
565 }
566 /* Get the context for this user, adding if not yet present */
567 context = otrl_context_find(us, username, accountname, protocol,
568 1, NULL, add_app_data, data);
569 /* Add the fingerprint if not already there */
570 fng = otrl_context_find_fingerprint(context, fingerprint, 1, NULL);
571 otrl_context_set_trust(fng, trust);
572 }
573
574 return gcry_error(GPG_ERR_NO_ERROR);
575}
576
577/* Write the fingerprint store from a given OtrlUserState to a file on disk. */
578gcry_error_t otrl_privkey_write_fingerprints(OtrlUserState us,
579 const char *filename)
580{
581 gcry_error_t err;
582 FILE *storef;
583
584 storef = fopen(filename, "wb");
585 if (!storef) {
586 err = gcry_error_from_errno(errno);
587 return err;
588 }
589
590 err = otrl_privkey_write_fingerprints_FILEp(us, storef);
591
592 fclose(storef);
593 return err;
594}
595
596/* Write the fingerprint store from a given OtrlUserState to a FILE*.
597 * The FILE* must be open for writing. */
598gcry_error_t otrl_privkey_write_fingerprints_FILEp(OtrlUserState us,
599 FILE *storef)
600{
601 ConnContext *context;
602 Fingerprint *fprint;
603
604 if (!storef) return gcry_error(GPG_ERR_NO_ERROR);
605
606 for(context = us->context_root; context; context = context->next) {
607 /* Don't both with the first (fingerprintless) entry. */
608 for (fprint = context->fingerprint_root.next; fprint;
609 fprint = fprint->next) {
610 int i;
611 fprintf(storef, "%s\t%s\t%s\t", context->username,
612 context->accountname, context->protocol);
613 for(i=0;i<20;++i) {
614 fprintf(storef, "%02x", fprint->fingerprint[i]);
615 }
616 fprintf(storef, "\t%s\n", fprint->trust ? fprint->trust : "");
617 }
618 }
619
620 return gcry_error(GPG_ERR_NO_ERROR);
621}
622
623/* Fetch the private key from the given OtrlUserState associated with
624 * the given account */
625OtrlPrivKey *otrl_privkey_find(OtrlUserState us, const char *accountname,
626 const char *protocol)
627{
628 OtrlPrivKey *p;
629 if (!accountname || !protocol) return NULL;
630
631 for(p=us->privkey_root; p; p=p->next) {
632 if (!strcmp(p->accountname, accountname) &&
633 !strcmp(p->protocol, protocol)) {
634 return p;
635 }
636 }
637 return NULL;
638}
639
640/* Forget a private key */
641void otrl_privkey_forget(OtrlPrivKey *privkey)
642{
643 free(privkey->accountname);
644 free(privkey->protocol);
645 gcry_sexp_release(privkey->privkey);
646 free(privkey->pubkey_data);
647
648 /* Re-link the list */
649 *(privkey->tous) = privkey->next;
650 if (privkey->next) {
651 privkey->next->tous = privkey->tous;
652 }
653
654 /* Free the privkey struct */
655 free(privkey);
656}
657
658/* Forget all private keys in a given OtrlUserState. */
659void otrl_privkey_forget_all(OtrlUserState us)
660{
661 while (us->privkey_root) {
662 otrl_privkey_forget(us->privkey_root);
663 }
664}
665
666/* Sign data using a private key. The data must be small enough to be
667 * signed (i.e. already hashed, if necessary). The signature will be
668 * returned in *sigp, which the caller must free(). Its length will be
669 * returned in *siglenp. */
670gcry_error_t otrl_privkey_sign(unsigned char **sigp, size_t *siglenp,
671 OtrlPrivKey *privkey, const unsigned char *data, size_t len)
672{
673 gcry_mpi_t r,s, datampi;
674 gcry_sexp_t dsas, rs, ss, sigs, datas;
675 size_t nr, ns;
676 const enum gcry_mpi_format format = GCRYMPI_FMT_USG;
677
678 if (privkey->pubkey_type != OTRL_PUBKEY_TYPE_DSA)
679 return gcry_error(GPG_ERR_INV_VALUE);
680
681 *sigp = malloc(40);
682 if (sigp == NULL) return gcry_error(GPG_ERR_ENOMEM);
683 *siglenp = 40;
684
685 if (len) {
686 gcry_mpi_scan(&datampi, GCRYMPI_FMT_USG, data, len, NULL);
687 } else {
688 datampi = gcry_mpi_set_ui(NULL, 0);
689 }
690 gcry_sexp_build(&datas, NULL, "(%m)", datampi);
691 gcry_mpi_release(datampi);
692 gcry_pk_sign(&sigs, datas, privkey->privkey);
693 gcry_sexp_release(datas);
694 dsas = gcry_sexp_find_token(sigs, "dsa", 0);
695 gcry_sexp_release(sigs);
696 rs = gcry_sexp_find_token(dsas, "r", 0);
697 ss = gcry_sexp_find_token(dsas, "s", 0);
698 gcry_sexp_release(dsas);
699 r = gcry_sexp_nth_mpi(rs, 1, GCRYMPI_FMT_USG);
700 gcry_sexp_release(rs);
701 s = gcry_sexp_nth_mpi(ss, 1, GCRYMPI_FMT_USG);
702 gcry_sexp_release(ss);
703 gcry_mpi_print(format, NULL, 0, &nr, r);
704 gcry_mpi_print(format, NULL, 0, &ns, s);
705 memset(*sigp, 0, 40);
706 gcry_mpi_print(format, (*sigp)+(20-nr), nr, NULL, r);
707 gcry_mpi_print(format, (*sigp)+20+(20-ns), ns, NULL, s);
708 gcry_mpi_release(r);
709 gcry_mpi_release(s);
710
711 return gcry_error(GPG_ERR_NO_ERROR);
712}
713
714/* Verify a signature on data using a public key. The data must be
715 * small enough to be signed (i.e. already hashed, if necessary). */
716gcry_error_t otrl_privkey_verify(const unsigned char *sigbuf, size_t siglen,
717 unsigned short pubkey_type, gcry_sexp_t pubs,
718 const unsigned char *data, size_t len)
719{
720 gcry_error_t err;
721 gcry_mpi_t datampi,r,s;
722 gcry_sexp_t datas, sigs;
723
724 if (pubkey_type != OTRL_PUBKEY_TYPE_DSA || siglen != 40)
725 return gcry_error(GPG_ERR_INV_VALUE);
726
727 if (len) {
728 gcry_mpi_scan(&datampi, GCRYMPI_FMT_USG, data, len, NULL);
729 } else {
730 datampi = gcry_mpi_set_ui(NULL, 0);
731 }
732 gcry_sexp_build(&datas, NULL, "(%m)", datampi);
733 gcry_mpi_release(datampi);
734 gcry_mpi_scan(&r, GCRYMPI_FMT_USG, sigbuf, 20, NULL);
735 gcry_mpi_scan(&s, GCRYMPI_FMT_USG, sigbuf+20, 20, NULL);
736 gcry_sexp_build(&sigs, NULL, "(sig-val (dsa (r %m)(s %m)))", r, s);
737 gcry_mpi_release(r);
738 gcry_mpi_release(s);
739
740 err = gcry_pk_verify(sigs, datas, pubs);
741 gcry_sexp_release(datas);
742 gcry_sexp_release(sigs);
743
744 return err;
745}
diff --git a/linden/indra/libotr/libotr-3.2.0/src/privkey.h b/linden/indra/libotr/libotr-3.2.0/src/privkey.h
new file mode 100755
index 0000000..83e7d48
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/privkey.h
@@ -0,0 +1,112 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef __PRIVKEY_H__
21#define __PRIVKEY_H__
22
23#include <stdio.h>
24#include "privkey-t.h"
25#include "userstate.h"
26
27/* Convert a 20-byte hash value to a 45-byte human-readable value */
28void otrl_privkey_hash_to_human(char human[45], const unsigned char hash[20]);
29
30/* Calculate a human-readable hash of our DSA public key. Return it in
31 * the passed fingerprint buffer. Return NULL on error, or a pointer to
32 * the given buffer on success. */
33char *otrl_privkey_fingerprint(OtrlUserState us, char fingerprint[45],
34 const char *accountname, const char *protocol);
35
36/* Calculate a raw hash of our DSA public key. Return it in the passed
37 * fingerprint buffer. Return NULL on error, or a pointer to the given
38 * buffer on success. */
39unsigned char *otrl_privkey_fingerprint_raw(OtrlUserState us,
40 unsigned char hash[20], const char *accountname, const char *protocol);
41
42/* Read a sets of private DSA keys from a file on disk into the given
43 * OtrlUserState. */
44gcry_error_t otrl_privkey_read(OtrlUserState us, const char *filename);
45
46/* Read a sets of private DSA keys from a FILE* into the given
47 * OtrlUserState. The FILE* must be open for reading. */
48gcry_error_t otrl_privkey_read_FILEp(OtrlUserState us, FILE *privf);
49
50/* Generate a private DSA key for a given account, storing it into a
51 * file on disk, and loading it into the given OtrlUserState. Overwrite any
52 * previously generated keys for that account in that OtrlUserState. */
53gcry_error_t otrl_privkey_generate(OtrlUserState us, const char *filename,
54 const char *accountname, const char *protocol);
55
56/* Generate a private DSA key for a given account, storing it into a
57 * FILE*, and loading it into the given OtrlUserState. Overwrite any
58 * previously generated keys for that account in that OtrlUserState.
59 * The FILE* must be open for reading and writing. */
60gcry_error_t otrl_privkey_generate_FILEp(OtrlUserState us, FILE *privf,
61 const char *accountname, const char *protocol);
62
63/* Read the fingerprint store from a file on disk into the given
64 * OtrlUserState. Use add_app_data to add application data to each
65 * ConnContext so created. */
66gcry_error_t otrl_privkey_read_fingerprints(OtrlUserState us,
67 const char *filename,
68 void (*add_app_data)(void *data, ConnContext *context),
69 void *data);
70
71/* Read the fingerprint store from a FILE* into the given
72 * OtrlUserState. Use add_app_data to add application data to each
73 * ConnContext so created. The FILE* must be open for reading. */
74gcry_error_t otrl_privkey_read_fingerprints_FILEp(OtrlUserState us,
75 FILE *storef,
76 void (*add_app_data)(void *data, ConnContext *context),
77 void *data);
78
79/* Write the fingerprint store from a given OtrlUserState to a file on disk. */
80gcry_error_t otrl_privkey_write_fingerprints(OtrlUserState us,
81 const char *filename);
82
83/* Write the fingerprint store from a given OtrlUserState to a FILE*.
84 * The FILE* must be open for writing. */
85gcry_error_t otrl_privkey_write_fingerprints_FILEp(OtrlUserState us,
86 FILE *storef);
87
88/* Fetch the private key from the given OtrlUserState associated with
89 * the given account */
90OtrlPrivKey *otrl_privkey_find(OtrlUserState us, const char *accountname,
91 const char *protocol);
92
93/* Forget a private key */
94void otrl_privkey_forget(OtrlPrivKey *privkey);
95
96/* Forget all private keys in a given OtrlUserState. */
97void otrl_privkey_forget_all(OtrlUserState us);
98
99/* Sign data using a private key. The data must be small enough to be
100 * signed (i.e. already hashed, if necessary). The signature will be
101 * returned in *sigp, which the caller must free(). Its length will be
102 * returned in *siglenp. */
103gcry_error_t otrl_privkey_sign(unsigned char **sigp, size_t *siglenp,
104 OtrlPrivKey *privkey, const unsigned char *data, size_t len);
105
106/* Verify a signature on data using a public key. The data must be
107 * small enough to be signed (i.e. already hashed, if necessary). */
108gcry_error_t otrl_privkey_verify(const unsigned char *sigbuf, size_t siglen,
109 unsigned short pubkey_type, gcry_sexp_t pubs,
110 const unsigned char *data, size_t len);
111
112#endif
diff --git a/linden/indra/libotr/libotr-3.2.0/src/proto.c b/linden/indra/libotr/libotr-3.2.0/src/proto.c
new file mode 100755
index 0000000..2044e06
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/proto.c
@@ -0,0 +1,998 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/* OTR Protocol implementation. This file should be independent of
21 * gaim, so that it can be used to make other clients. */
22
23/* system headers */
24#include <stdio.h>
25#include <stdlib.h>
26#include <assert.h>
27
28/* libgcrypt headers */
29#include <gcrypt.h>
30
31/* libotr headers */
32#include "b64.h"
33#include "privkey.h"
34#include "proto.h"
35#include "mem.h"
36#include "version.h"
37#include "tlv.h"
38#include "serial.h"
39
40/* For now, we need to know the API version the client is using so that
41 * we don't use any UI callbacks it hasn't set. */
42unsigned int otrl_api_version = 0;
43
44/* Initialize the OTR library. Pass the version of the API you are
45 * using. */
46void otrl_init(unsigned int ver_major, unsigned int ver_minor,
47 unsigned int ver_sub)
48{
49 unsigned int api_version;
50
51 /* The major versions have to match, and you can't be using a newer
52 * minor version than we expect. */
53 if (ver_major != OTRL_VERSION_MAJOR || ver_minor > OTRL_VERSION_MINOR) {
54 fprintf(stderr, "Expected libotr API version %u.%u.%u incompatible "
55 "with actual version %u.%u.%u. Aborting.\n",
56 ver_major, ver_minor, ver_sub,
57 OTRL_VERSION_MAJOR, OTRL_VERSION_MINOR, OTRL_VERSION_SUB);
58 exit(1);
59 }
60
61 /* Set the API version. If we get called multiple times for some
62 * reason, take the smallest value. */
63 api_version = (ver_major << 16) | (ver_minor << 8) | (ver_sub);
64 if (otrl_api_version == 0 || otrl_api_version > api_version) {
65 otrl_api_version = api_version;
66 }
67
68 /* Initialize the memory module */
69 otrl_mem_init();
70
71 /* Initialize the DH module */
72 otrl_dh_init();
73
74 /* Initialize the SM module */
75 otrl_sm_init();
76}
77
78/* Return a pointer to a static string containing the version number of
79 * the OTR library. */
80const char *otrl_version(void)
81{
82 return OTRL_VERSION;
83}
84
85/* Store some MAC keys to be revealed later */
86static gcry_error_t reveal_macs(ConnContext *context,
87 DH_sesskeys *sess1, DH_sesskeys *sess2)
88{
89 unsigned int numnew = sess1->rcvmacused + sess1->sendmacused +
90 sess2->rcvmacused + sess2->sendmacused;
91 unsigned int newnumsaved;
92 unsigned char *newmacs;
93
94 /* Is there anything to do? */
95 if (numnew == 0) return gcry_error(GPG_ERR_NO_ERROR);
96
97 newnumsaved = context->numsavedkeys + numnew;
98 newmacs = realloc(context->saved_mac_keys,
99 newnumsaved * 20);
100 if (!newmacs) {
101 return gcry_error(GPG_ERR_ENOMEM);
102 }
103 if (sess1->rcvmacused) {
104 memmove(newmacs + context->numsavedkeys * 20, sess1->rcvmackey, 20);
105 context->numsavedkeys++;
106 }
107 if (sess1->sendmacused) {
108 memmove(newmacs + context->numsavedkeys * 20, sess1->sendmackey, 20);
109 context->numsavedkeys++;
110 }
111 if (sess2->rcvmacused) {
112 memmove(newmacs + context->numsavedkeys * 20, sess2->rcvmackey, 20);
113 context->numsavedkeys++;
114 }
115 if (sess2->sendmacused) {
116 memmove(newmacs + context->numsavedkeys * 20, sess2->sendmackey, 20);
117 context->numsavedkeys++;
118 }
119 context->saved_mac_keys = newmacs;
120
121 return gcry_error(GPG_ERR_NO_ERROR);
122}
123
124/* Make a new DH key for us, and rotate old old ones. Be sure to keep
125 * the sesskeys array in sync. */
126static gcry_error_t rotate_dh_keys(ConnContext *context)
127{
128 gcry_error_t err;
129
130 /* Rotate the keypair */
131 otrl_dh_keypair_free(&(context->our_old_dh_key));
132 memmove(&(context->our_old_dh_key), &(context->our_dh_key),
133 sizeof(DH_keypair));
134
135 /* Rotate the session keys */
136 err = reveal_macs(context, &(context->sesskeys[1][0]),
137 &(context->sesskeys[1][1]));
138 if (err) return err;
139 otrl_dh_session_free(&(context->sesskeys[1][0]));
140 otrl_dh_session_free(&(context->sesskeys[1][1]));
141 memmove(&(context->sesskeys[1][0]), &(context->sesskeys[0][0]),
142 sizeof(DH_sesskeys));
143 memmove(&(context->sesskeys[1][1]), &(context->sesskeys[0][1]),
144 sizeof(DH_sesskeys));
145
146 /* Create a new DH key */
147 otrl_dh_gen_keypair(DH1536_GROUP_ID, &(context->our_dh_key));
148 context->our_keyid++;
149
150 /* Make the session keys */
151 if (context->their_y) {
152 err = otrl_dh_session(&(context->sesskeys[0][0]),
153 &(context->our_dh_key), context->their_y);
154 if (err) return err;
155 } else {
156 otrl_dh_session_blank(&(context->sesskeys[0][0]));
157 }
158 if (context->their_old_y) {
159 err = otrl_dh_session(&(context->sesskeys[0][1]),
160 &(context->our_dh_key), context->their_old_y);
161 if (err) return err;
162 } else {
163 otrl_dh_session_blank(&(context->sesskeys[0][1]));
164 }
165 return gcry_error(GPG_ERR_NO_ERROR);
166}
167
168/* Rotate in a new DH public key for our correspondent. Be sure to keep
169 * the sesskeys array in sync. */
170static gcry_error_t rotate_y_keys(ConnContext *context, gcry_mpi_t new_y)
171{
172 gcry_error_t err;
173
174 /* Rotate the public key */
175 gcry_mpi_release(context->their_old_y);
176 context->their_old_y = context->their_y;
177
178 /* Rotate the session keys */
179 err = reveal_macs(context, &(context->sesskeys[0][1]),
180 &(context->sesskeys[1][1]));
181 if (err) return err;
182 otrl_dh_session_free(&(context->sesskeys[0][1]));
183 otrl_dh_session_free(&(context->sesskeys[1][1]));
184 memmove(&(context->sesskeys[0][1]), &(context->sesskeys[0][0]),
185 sizeof(DH_sesskeys));
186 memmove(&(context->sesskeys[1][1]), &(context->sesskeys[1][0]),
187 sizeof(DH_sesskeys));
188
189 /* Copy in the new public key */
190 context->their_y = gcry_mpi_copy(new_y);
191 context->their_keyid++;
192
193 /* Make the session keys */
194 err = otrl_dh_session(&(context->sesskeys[0][0]),
195 &(context->our_dh_key), context->their_y);
196 if (err) return err;
197 err = otrl_dh_session(&(context->sesskeys[1][0]),
198 &(context->our_old_dh_key), context->their_y);
199 if (err) return err;
200
201 return gcry_error(GPG_ERR_NO_ERROR);
202}
203
204/* Return a pointer to a newly-allocated OTR query message, customized
205 * with our name. The caller should free() the result when he's done
206 * with it. */
207char *otrl_proto_default_query_msg(const char *ourname, OtrlPolicy policy)
208{
209 char *msg;
210 int v1_supported, v2_supported;
211 const char *version_tag;
212 /* Don't use g_strdup_printf here, because someone (not us) is going
213 * to free() the *message pointer, not g_free() it. We can't
214 * require that they g_free() it, because this pointer will probably
215 * get passed to the main IM application for processing (and
216 * free()ing). */
217 const char *format = "?OTR%s\n%s has requested an Off-the-Record "
218 "private conversation. However, your viewer doesn't support "
219 "OTR. Emerald Viewer does, see "
220 "http://modularsystems.sl/ for more information about GreenLife, "
221 "and http://otr.cypherpunks.ca/ for more information about OTR.";
222
223 /* Figure out the version tag */
224 v1_supported = (policy & OTRL_POLICY_ALLOW_V1);
225 v2_supported = (policy & OTRL_POLICY_ALLOW_V2);
226 if (v1_supported) {
227 if (v2_supported) {
228 version_tag = "?v2?";
229 } else {
230 version_tag = "?";
231 }
232 } else {
233 if (v2_supported) {
234 version_tag = "v2?";
235 } else {
236 version_tag = "v?";
237 }
238 }
239
240 /* Remove two "%s", add '\0' */
241 msg = malloc(strlen(format) + strlen(version_tag) + strlen(ourname) - 3);
242 if (!msg) return NULL;
243 sprintf(msg, format, version_tag, ourname);
244 return msg;
245}
246
247/* Return the best version of OTR support by both sides, given an OTR
248 * Query Message and the local policy. */
249unsigned int otrl_proto_query_bestversion(const char *querymsg,
250 OtrlPolicy policy)
251{
252 char *otrtag;
253 unsigned int query_versions = 0;
254
255 otrtag = strstr(querymsg, "?OTR");
256 otrtag += 4;
257 if (*otrtag == '?') {
258 query_versions = (1<<0);
259 ++otrtag;
260 }
261 if (*otrtag == 'v') {
262 for(++otrtag; *otrtag && *otrtag != '?'; ++otrtag) {
263 switch(*otrtag) {
264 case '2':
265 query_versions |= (1<<1);
266 break;
267 }
268 }
269 }
270
271 if ((policy & OTRL_POLICY_ALLOW_V2) && (query_versions & (1<<1))) {
272 return 2;
273 }
274 if ((policy & OTRL_POLICY_ALLOW_V1) && (query_versions & (1<<0))) {
275 return 1;
276 }
277 return 0;
278}
279
280/* Locate any whitespace tag in this message, and return the best
281 * version of OTR support on both sides. Set *starttagp and *endtagp to
282 * the start and end of the located tag, so that it can be snipped out. */
283unsigned int otrl_proto_whitespace_bestversion(const char *msg,
284 const char **starttagp, const char **endtagp, OtrlPolicy policy)
285{
286 const char *starttag, *endtag;
287 unsigned int query_versions = 0;
288
289 *starttagp = NULL;
290 *endtagp = NULL;
291
292 starttag = strstr(msg, OTRL_MESSAGE_TAG_BASE);
293 if (!starttag) return 0;
294
295 endtag = starttag + strlen(OTRL_MESSAGE_TAG_BASE);
296
297 /* Look for groups of 8 spaces and/or tabs */
298 while(1) {
299 int i;
300 int allwhite = 1;
301 for(i=0;i<8;++i) {
302 if (endtag[i] != ' ' && endtag[i] != '\t') {
303 allwhite = 0;
304 break;
305 }
306 }
307 if (allwhite) {
308 if (!strncmp(endtag, OTRL_MESSAGE_TAG_V1, 8)) {
309 query_versions |= (1<<0);
310 }
311 if (!strncmp(endtag, OTRL_MESSAGE_TAG_V2, 8)) {
312 query_versions |= (1<<1);
313 }
314 endtag += 8;
315 } else {
316 break;
317 }
318 }
319
320 *starttagp = starttag;
321 *endtagp = endtag;
322
323 if ((policy & OTRL_POLICY_ALLOW_V2) && (query_versions & (1<<1))) {
324 return 2;
325 }
326 if ((policy & OTRL_POLICY_ALLOW_V1) && (query_versions & (1<<0))) {
327 return 1;
328 }
329 return 0;
330}
331
332/* Return the Message type of the given message. */
333OtrlMessageType otrl_proto_message_type(const char *message)
334{
335 char *otrtag;
336
337 otrtag = strstr(message, "?OTR");
338
339 if (!otrtag) {
340 if (strstr(message, OTRL_MESSAGE_TAG_BASE)) {
341 return OTRL_MSGTYPE_TAGGEDPLAINTEXT;
342 } else {
343 return OTRL_MSGTYPE_NOTOTR;
344 }
345 }
346
347 if (!strncmp(otrtag, "?OTR?", 5)) return OTRL_MSGTYPE_QUERY;
348 if (!strncmp(otrtag, "?OTRv", 5)) return OTRL_MSGTYPE_QUERY;
349 if (!strncmp(otrtag, "?OTR:AAIC", 9)) return OTRL_MSGTYPE_DH_COMMIT;
350 if (!strncmp(otrtag, "?OTR:AAIK", 9)) return OTRL_MSGTYPE_DH_KEY;
351 if (!strncmp(otrtag, "?OTR:AAIR", 9)) return OTRL_MSGTYPE_REVEALSIG;
352 if (!strncmp(otrtag, "?OTR:AAIS", 9)) return OTRL_MSGTYPE_SIGNATURE;
353 if (!strncmp(otrtag, "?OTR:AAEK", 9)) return OTRL_MSGTYPE_V1_KEYEXCH;
354 if (!strncmp(otrtag, "?OTR:AAED", 9)) return OTRL_MSGTYPE_DATA;
355 if (!strncmp(otrtag, "?OTR:AAID", 9)) return OTRL_MSGTYPE_DATA;
356 if (!strncmp(otrtag, "?OTR Error:", 11)) return OTRL_MSGTYPE_ERROR;
357
358 return OTRL_MSGTYPE_UNKNOWN;
359}
360
361/* Create an OTR Data message. Pass the plaintext as msg, and an
362 * optional chain of TLVs. A newly-allocated string will be returned in
363 * *encmessagep. */
364gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context,
365 const char *msg, const OtrlTLV *tlvs, unsigned char flags)
366{
367 size_t justmsglen = strlen(msg);
368 size_t msglen = justmsglen + 1 + otrl_tlv_seriallen(tlvs);
369 size_t buflen;
370 size_t pubkeylen;
371 unsigned char *buf = NULL;
372 unsigned char *bufp;
373 size_t lenp;
374 DH_sesskeys *sess = &(context->sesskeys[1][0]);
375 gcry_error_t err;
376 size_t reveallen = 20 * context->numsavedkeys;
377 size_t base64len;
378 char *base64buf = NULL;
379 unsigned char *msgbuf = NULL;
380 enum gcry_mpi_format format = GCRYMPI_FMT_USG;
381 char *msgdup;
382 int version = context->protocol_version;
383
384 /* Make sure we're actually supposed to be able to encrypt */
385 if (context->msgstate != OTRL_MSGSTATE_ENCRYPTED ||
386 context->their_keyid == 0) {
387 return gcry_error(GPG_ERR_CONFLICT);
388 }
389
390 /* We need to copy the incoming msg, since it might be an alias for
391 * context->lastmessage, which we'll be freeing soon. */
392 msgdup = gcry_malloc_secure(justmsglen + 1);
393 if (msgdup == NULL) {
394 return gcry_error(GPG_ERR_ENOMEM);
395 }
396 strcpy(msgdup, msg);
397
398 *encmessagep = NULL;
399
400 /* Header, send keyid, recv keyid, counter, msg len, msg
401 * len of revealed mac keys, revealed mac keys, MAC */
402 buflen = 3 + (version == 2 ? 1 : 0) + 4 + 4 + 8 + 4 + msglen +
403 4 + reveallen + 20;
404 gcry_mpi_print(format, NULL, 0, &pubkeylen, context->our_dh_key.pub);
405 buflen += pubkeylen + 4;
406 buf = malloc(buflen);
407 msgbuf = gcry_malloc_secure(msglen);
408 if (buf == NULL || msgbuf == NULL) {
409 free(buf);
410 gcry_free(msgbuf);
411 gcry_free(msgdup);
412 return gcry_error(GPG_ERR_ENOMEM);
413 }
414 memmove(msgbuf, msgdup, justmsglen);
415 msgbuf[justmsglen] = '\0';
416 otrl_tlv_serialize(msgbuf + justmsglen + 1, tlvs);
417 bufp = buf;
418 lenp = buflen;
419 if (version == 1) {
420 memmove(bufp, "\x00\x01\x03", 3); /* header */
421 } else {
422 memmove(bufp, "\x00\x02\x03", 3); /* header */
423 }
424 debug_data("Header", bufp, 3);
425 bufp += 3; lenp -= 3;
426 if (version == 2) {
427 bufp[0] = flags;
428 bufp += 1; lenp -= 1;
429 }
430 write_int(context->our_keyid-1); /* sender keyid */
431 debug_int("Sender keyid", bufp-4);
432 write_int(context->their_keyid); /* recipient keyid */
433 debug_int("Recipient keyid", bufp-4);
434
435 write_mpi(context->our_dh_key.pub, pubkeylen, "Y"); /* Y */
436
437 otrl_dh_incctr(sess->sendctr);
438 memmove(bufp, sess->sendctr, 8); /* Counter (top 8 bytes only) */
439 debug_data("Counter", bufp, 8);
440 bufp += 8; lenp -= 8;
441
442 write_int(msglen); /* length of encrypted data */
443 debug_int("Msg len", bufp-4);
444
445 err = gcry_cipher_reset(sess->sendenc);
446 if (err) goto err;
447 err = gcry_cipher_setctr(sess->sendenc, sess->sendctr, 16);
448 if (err) goto err;
449 err = gcry_cipher_encrypt(sess->sendenc, bufp, msglen, msgbuf, msglen);
450 if (err) goto err; /* encrypted data */
451 debug_data("Enc data", bufp, msglen);
452 bufp += msglen;
453 lenp -= msglen;
454
455 gcry_md_reset(sess->sendmac);
456 gcry_md_write(sess->sendmac, buf, bufp-buf);
457 memmove(bufp, gcry_md_read(sess->sendmac, GCRY_MD_SHA1), 20);
458 debug_data("MAC", bufp, 20);
459 bufp += 20; /* MAC */
460 lenp -= 20;
461
462 write_int(reveallen); /* length of revealed MAC keys */
463 debug_int("Revealed MAC length", bufp-4);
464
465 if (reveallen > 0) {
466 memmove(bufp, context->saved_mac_keys, reveallen);
467 debug_data("Revealed MAC data", bufp, reveallen);
468 bufp += reveallen; lenp -= reveallen;
469 free(context->saved_mac_keys);
470 context->saved_mac_keys = NULL;
471 context->numsavedkeys = 0;
472 }
473
474 assert(lenp == 0);
475
476 /* Make the base64-encoding. */
477 base64len = ((buflen + 2) / 3) * 4;
478 base64buf = malloc(5 + base64len + 1 + 1);
479 if (base64buf == NULL) {
480 err = gcry_error(GPG_ERR_ENOMEM);
481 goto err;
482 }
483 memmove(base64buf, "?OTR:", 5);
484 otrl_base64_encode(base64buf+5, buf, buflen);
485 base64buf[5 + base64len] = '.';
486 base64buf[5 + base64len + 1] = '\0';
487
488 free(buf);
489 gcry_free(msgbuf);
490 *encmessagep = base64buf;
491 gcry_free(context->lastmessage);
492 context->lastmessage = NULL;
493 context->may_retransmit = 0;
494 if (msglen > 0) {
495 const char *prefix = "[resent] ";
496 size_t prefixlen = strlen(prefix);
497 if (!strncmp(prefix, msgdup, prefixlen)) {
498 /* The prefix is already there. Don't add it again. */
499 prefix = "";
500 prefixlen = 0;
501 }
502 context->lastmessage = gcry_malloc_secure(prefixlen + justmsglen + 1);
503 if (context->lastmessage) {
504 strcpy(context->lastmessage, prefix);
505 strcat(context->lastmessage, msgdup);
506 }
507 }
508 gcry_free(msgdup);
509 return gcry_error(GPG_ERR_NO_ERROR);
510err:
511 free(buf);
512 gcry_free(msgbuf);
513 gcry_free(msgdup);
514 *encmessagep = NULL;
515 return err;
516}
517
518/* Extract the flags from an otherwise unreadable Data Message. */
519gcry_error_t otrl_proto_data_read_flags(const char *datamsg,
520 unsigned char *flagsp)
521{
522 char *otrtag, *endtag;
523 unsigned char *rawmsg = NULL;
524 unsigned char *bufp;
525 size_t msglen, rawlen, lenp;
526 unsigned char version;
527
528 if (flagsp) *flagsp = 0;
529 otrtag = strstr(datamsg, "?OTR:");
530 if (!otrtag) {
531 goto invval;
532 }
533 endtag = strchr(otrtag, '.');
534 if (endtag) {
535 msglen = endtag-otrtag;
536 } else {
537 msglen = strlen(otrtag);
538 }
539
540 /* Base64-decode the message */
541 rawlen = ((msglen-5) / 4) * 3; /* maximum possible */
542 rawmsg = malloc(rawlen);
543 if (!rawmsg && rawlen > 0) {
544 return gcry_error(GPG_ERR_ENOMEM);
545 }
546 rawlen = otrl_base64_decode(rawmsg, otrtag+5, msglen-5); /* actual size */
547
548 bufp = rawmsg;
549 lenp = rawlen;
550
551 require_len(3);
552 if (memcmp(bufp, "\x00\x01\x03", 3) && memcmp(bufp, "\x00\x02\x03", 3)) {
553 /* Invalid header */
554 goto invval;
555 }
556 version = bufp[1];
557 bufp += 3; lenp -= 3;
558
559 if (version == 2) {
560 require_len(1);
561 if (flagsp) *flagsp = bufp[0];
562 bufp += 1; lenp -= 1;
563 }
564
565 free(rawmsg);
566 return gcry_error(GPG_ERR_NO_ERROR);
567
568invval:
569 free(rawmsg);
570 return gcry_error(GPG_ERR_INV_VALUE);
571}
572
573/* Accept an OTR Data Message in datamsg. Decrypt it and put the
574 * plaintext into *plaintextp, and any TLVs into tlvsp. Put any
575 * received flags into *flagsp (if non-NULL). */
576gcry_error_t otrl_proto_accept_data(char **plaintextp, OtrlTLV **tlvsp,
577 ConnContext *context, const char *datamsg, unsigned char *flagsp)
578{
579 char *otrtag, *endtag;
580 gcry_error_t err;
581 unsigned char *rawmsg = NULL;
582 size_t msglen, rawlen, lenp;
583 unsigned char *macstart, *macend;
584 unsigned char *bufp;
585 unsigned int sender_keyid, recipient_keyid;
586 gcry_mpi_t sender_next_y = NULL;
587 unsigned char ctr[8];
588 unsigned int datalen, reveallen;
589 unsigned char *data = NULL;
590 unsigned char *nul = NULL;
591 unsigned char givenmac[20];
592 DH_sesskeys *sess;
593 unsigned char version;
594
595 *plaintextp = NULL;
596 *tlvsp = NULL;
597 if (flagsp) *flagsp = 0;
598 otrtag = strstr(datamsg, "?OTR:");
599 if (!otrtag) {
600 goto invval;
601 }
602 endtag = strchr(otrtag, '.');
603 if (endtag) {
604 msglen = endtag-otrtag;
605 } else {
606 msglen = strlen(otrtag);
607 }
608
609 /* Base64-decode the message */
610 rawlen = ((msglen-5) / 4) * 3; /* maximum possible */
611 rawmsg = malloc(rawlen);
612 if (!rawmsg && rawlen > 0) {
613 err = gcry_error(GPG_ERR_ENOMEM);
614 goto err;
615 }
616 rawlen = otrl_base64_decode(rawmsg, otrtag+5, msglen-5); /* actual size */
617
618 bufp = rawmsg;
619 lenp = rawlen;
620
621 macstart = bufp;
622 require_len(3);
623 if (memcmp(bufp, "\x00\x01\x03", 3) && memcmp(bufp, "\x00\x02\x03", 3)) {
624 /* Invalid header */
625 goto invval;
626 }
627 version = bufp[1];
628 bufp += 3; lenp -= 3;
629
630 if (version == 2) {
631 require_len(1);
632 if (flagsp) *flagsp = bufp[0];
633 bufp += 1; lenp -= 1;
634 }
635 read_int(sender_keyid);
636 read_int(recipient_keyid);
637 read_mpi(sender_next_y);
638 require_len(8);
639 memmove(ctr, bufp, 8);
640 bufp += 8; lenp -= 8;
641 read_int(datalen);
642 require_len(datalen);
643 data = malloc(datalen+1);
644 if (!data) {
645 err = gcry_error(GPG_ERR_ENOMEM);
646 goto err;
647 }
648 memmove(data, bufp, datalen);
649 data[datalen] = '\0';
650 bufp += datalen; lenp -= datalen;
651 macend = bufp;
652 require_len(20);
653 memmove(givenmac, bufp, 20);
654 bufp += 20; lenp -= 20;
655 read_int(reveallen);
656 require_len(reveallen);
657 /* Just skip over the revealed MAC keys, which we don't need. They
658 * were published for deniability of transcripts. */
659 bufp += reveallen; lenp -= reveallen;
660
661 /* That should be everything */
662 if (lenp != 0) goto invval;
663
664 /* We don't take any action on this message (especially rotating
665 * keys) until we've verified the MAC on this message. To that end,
666 * we need to know which keys this message is claiming to use. */
667 if (context->their_keyid == 0 ||
668 (sender_keyid != context->their_keyid &&
669 sender_keyid != context->their_keyid - 1) ||
670 (recipient_keyid != context->our_keyid &&
671 recipient_keyid != context->our_keyid - 1) ||
672 sender_keyid == 0 || recipient_keyid == 0) {
673 goto conflict;
674 }
675
676 if (sender_keyid == context->their_keyid - 1 &&
677 context->their_old_y == NULL) {
678 goto conflict;
679 }
680
681 /* These are the session keys this message is claiming to use. */
682 sess = &(context->sesskeys
683 [context->our_keyid - recipient_keyid]
684 [context->their_keyid - sender_keyid]);
685
686 gcry_md_reset(sess->rcvmac);
687 gcry_md_write(sess->rcvmac, macstart, macend-macstart);
688 if (memcmp(givenmac, gcry_md_read(sess->rcvmac, GCRY_MD_SHA1), 20)) {
689 /* The MACs didn't match! */
690 goto conflict;
691 }
692 sess->rcvmacused = 1;
693
694 /* Check to see that the counter is increasing; i.e. that this isn't
695 * a replay. */
696 if (otrl_dh_cmpctr(ctr, sess->rcvctr) <= 0) {
697 goto conflict;
698 }
699
700 /* Decrypt the message */
701 memmove(sess->rcvctr, ctr, 8);
702 err = gcry_cipher_reset(sess->rcvenc);
703 if (err) goto err;
704 err = gcry_cipher_setctr(sess->rcvenc, sess->rcvctr, 16);
705 if (err) goto err;
706 err = gcry_cipher_decrypt(sess->rcvenc, data, datalen, NULL, 0);
707 if (err) goto err;
708
709 /* See if either set of keys needs rotating */
710
711 if (recipient_keyid == context->our_keyid) {
712 /* They're using our most recent key, so generate a new one */
713 err = rotate_dh_keys(context);
714 if (err) goto err;
715 }
716
717 if (sender_keyid == context->their_keyid) {
718 /* They've sent us a new public key */
719 err = rotate_y_keys(context, sender_next_y);
720 if (err) goto err;
721 }
722
723 gcry_mpi_release(sender_next_y);
724 *plaintextp = (char *)data;
725
726 /* See if there are TLVs */
727 nul = data;
728 while (nul < data+datalen && *nul) ++nul;
729 /* If we stopped before the end, skip the NUL we stopped at */
730 if (nul < data+datalen) ++nul;
731 *tlvsp = otrl_tlv_parse(nul, (data+datalen)-nul);
732
733 free(rawmsg);
734 return gcry_error(GPG_ERR_NO_ERROR);
735
736invval:
737 err = gcry_error(GPG_ERR_INV_VALUE);
738 goto err;
739conflict:
740 err = gcry_error(GPG_ERR_CONFLICT);
741 goto err;
742err:
743 gcry_mpi_release(sender_next_y);
744 free(data);
745 free(rawmsg);
746 return err;
747}
748
749/* free all the fragments we have collected */
750gcry_error_t otrl_free_fragments(ConnContext *context)
751{
752 if (!context)
753 {
754 /* $TODO$ better error code */
755 return gcry_error(GPG_ERR_CONFLICT);
756 }
757 else if (context->fragments)
758 {
759 int i;
760 for (i = 0; i < context->fragment_n; ++i)
761 {
762 if (context->fragments[i]) free(context->fragments[i]);
763 }
764 free(context->fragments);
765 }
766 context->fragments = NULL;
767 context->fragment_len = 0;
768 context->fragment_n = 0;
769 context->fragment_k = 0;
770 return gcry_error(GPG_ERR_NO_ERROR);
771}
772
773/* start collecting fragments */
774static gcry_error_t otrl_malloc_fragments(ConnContext *context, int how_many)
775{
776 if ((!context) || (how_many <= 0))
777 {
778 return gcry_error(GPG_ERR_CONFLICT); /* $TODO$ better error code */
779 }
780 else if (context->fragments)
781 {
782 otrl_free_fragments(context); /* shouldn't happen, but be resilient if it does */
783 }
784 context->fragments = (char **)malloc(how_many * sizeof(char *));
785 if (!context->fragments)
786 {
787 return gcry_error(GPG_ERR_ENOMEM);
788 }
789 else
790 {
791 int i;
792 for (i = 0; i < how_many; ++i)
793 {
794 context->fragments[i] = NULL;
795 }
796 context->fragment_n = how_many;
797 context->fragment_k = 0;
798 context->fragment_len = 0;
799 return gcry_error(GPG_ERR_NO_ERROR);
800 }
801}
802
803/* add a new fragment to our collection */
804static gcry_error_t otrl_add_fragment(ConnContext *context, int k, int len, const char *frag)
805{
806 if ((!context) || (!frag) || (k < 0) || (context->fragment_n <= k))
807 {
808 return gcry_error(GPG_ERR_CONFLICT); /* $TODO$ better error code */
809 }
810 context->fragments[k] = (char*)malloc(len + 1);
811 if (! context->fragments[k])
812 {
813 return gcry_error(GPG_ERR_ENOMEM);
814 }
815 memmove(context->fragments[k], frag, len);
816 context->fragments[k][len] = 0;
817 context->fragment_len += len;
818 context->fragment_k++;
819 return gcry_error(GPG_ERR_NO_ERROR);
820}
821
822/* put all the fragments together in one string */
823static gcry_error_t otrl_assemble_fragments(char **unfragmessagep, ConnContext *context)
824{
825 *unfragmessagep = (char *)malloc(context->fragment_len + 1);
826 if (! *unfragmessagep)
827 {
828 otrl_free_fragments(context);
829 return gcry_error(GPG_ERR_ENOMEM);
830 }
831 else
832 {
833 int i;
834 char *p = *unfragmessagep;
835 for (i = 0; i < context->fragment_n; ++i)
836 {
837 char *q = context->fragments[i];
838 if (!q)
839 {
840 /* inconsistent fragments */
841 free(*unfragmessagep);
842 *unfragmessagep = NULL;
843 otrl_free_fragments(context);
844 return gcry_error(GPG_ERR_CONFLICT); /* $TODO$ better error code */
845 }
846 while (*q) { *p = *q; p++; q++; }
847 }
848 *p = 0;
849 otrl_free_fragments(context);
850 return gcry_error(GPG_ERR_NO_ERROR);
851 }
852}
853
854/* Accumulate a potential fragment into the current context. */
855OtrlFragmentResult otrl_proto_fragment_accumulate(char **unfragmessagep,
856 ConnContext *context, const char *msg)
857{
858 OtrlFragmentResult res = OTRL_FRAGMENT_INCOMPLETE;
859 const char *tag;
860
861 tag = strstr(msg, "?OTR,");
862 if (! tag)
863 { /* not a fragmented message */
864 if (context->fragments)
865 {
866 /* We didn't get all of the last one. $TODO$ send NAK */
867 otrl_free_fragments(context);
868 }
869 res = OTRL_FRAGMENT_UNFRAGMENTED;
870 }
871 else
872 {
873 unsigned short n = 0, k = 0;
874 int start = 0, end = 0;
875 gcry_error_t err;
876
877 sscanf(tag, "?OTR,%hu,%hu,%n%*[^,],%n", &k, &n, &start, &end);
878 if (k > 0 && n > 0 && k <= n && start > 0 && end > 0 && start < end)
879 {
880 k--;
881 if (!context->fragments)
882 {
883 /* starting a new fragmented message */
884 err = otrl_malloc_fragments(context, n);
885 if (err) return OTRL_FRAGMENT_INCOMPLETE; /* $TODO$ */
886 }
887 else if (n != context->fragment_n)
888 {
889 /* must be starting a new message, but we didn't get
890 * all of the old one $TODO$ send a NAK */
891 otrl_free_fragments(context);
892 err = otrl_malloc_fragments(context, n);
893 if (err) return OTRL_FRAGMENT_INCOMPLETE; /* $TODO$ */
894 }
895 else if (context->fragments[k])
896 {
897 /* We already got fragment K. Not likely to be a
898 * duplicate, so this must be for a new message. But
899 * we didn't get all of the old one $TODO$ send a
900 * NAK */
901 otrl_free_fragments(context);
902 err = otrl_malloc_fragments(context, n);
903 if (err) return OTRL_FRAGMENT_INCOMPLETE; /* $TODO$ */
904 }
905 err = otrl_add_fragment(context, k, end - start - 1, tag + start);
906 if (err) return OTRL_FRAGMENT_INCOMPLETE; /* $TODO$ */
907 if (context->fragment_k == context->fragment_n)
908 {
909 err = otrl_assemble_fragments(unfragmessagep, context);
910 if (err) return OTRL_FRAGMENT_INCOMPLETE; /* $TODO$ */
911 else return OTRL_FRAGMENT_COMPLETE;
912 }
913 else
914 {
915 res = OTRL_FRAGMENT_INCOMPLETE;
916 }
917 }
918 }
919
920 return res;
921}
922
923/* Create a fragmented message. */
924gcry_error_t otrl_proto_fragment_create(int mms, int fragment_count,
925 char ***fragments, const char *message)
926{
927 char *fragdata;
928 int fragdatalen = 0;
929 unsigned short curfrag = 0;
930 int index = 0;
931 int msglen = strlen(message);
932 int headerlen = 19; /* Should vary by number of msgs */
933
934 char **fragmentarray = malloc(fragment_count * sizeof(char*));
935 if(!fragmentarray) return gcry_error(GPG_ERR_ENOMEM);
936
937 /*
938 * Find the next message fragment and store it in the array.
939 */
940 for(curfrag = 1; curfrag <= fragment_count; curfrag++) {
941 int i;
942 char *fragmentmsg;
943
944 if (msglen - index < mms - headerlen) {
945 fragdatalen = msglen - index;
946 } else {
947 fragdatalen = mms - headerlen;
948 }
949 fragdata = malloc(fragdatalen + 1);
950 if(!fragdata) {
951 for (i=0; i<curfrag-1; free(fragmentarray[i++])) {}
952 free(fragmentarray);
953 return gcry_error(GPG_ERR_ENOMEM);
954 }
955 strncpy(fragdata, message, fragdatalen);
956 fragdata[fragdatalen] = 0;
957
958 fragmentmsg = malloc(fragdatalen+headerlen+1);
959 if(!fragmentmsg) {
960 for (i=0; i<curfrag-1; free(fragmentarray[i++])) {}
961 free(fragmentarray);
962 free(fragdata);
963 return gcry_error(GPG_ERR_ENOMEM);
964 }
965
966 /*
967 * Create the actual fragment and store it in the array
968 */
969 snprintf(fragmentmsg, fragdatalen + headerlen, "?OTR,%05hu,%05hu,%s,", curfrag, fragment_count, fragdata);
970 fragmentmsg[fragdatalen + headerlen] = 0;
971
972 fragmentarray[curfrag-1] = fragmentmsg;
973
974 free(fragdata);
975 index += fragdatalen;
976 message += fragdatalen;
977 }
978
979 *fragments = fragmentarray;
980 return gcry_error(GPG_ERR_NO_ERROR);
981}
982
983/* Free a string array containing fragment messages. */
984void otrl_proto_fragment_free(char ***fragments, unsigned short arraylen)
985{
986 int i;
987 char **fragmentarray = *fragments;
988 if(fragmentarray) {
989 for(i = 0; i < arraylen; i++)
990 {
991 if(fragmentarray[i]) {
992 free(fragmentarray[i]);
993 }
994 }
995 free(fragmentarray);
996 }
997}
998
diff --git a/linden/indra/libotr/libotr-3.2.0/src/proto.h b/linden/indra/libotr/libotr-3.2.0/src/proto.h
new file mode 100755
index 0000000..20b3a18
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/proto.h
@@ -0,0 +1,153 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef __PROTO_H__
21#define __PROTO_H__
22
23#include "context.h"
24#include "version.h"
25#include "tlv.h"
26
27/* If we ever see this sequence in a plaintext message, we'll assume the
28 * other side speaks OTR, and try to establish a connection. */
29#define OTRL_MESSAGE_TAG_BASE " \t \t\t\t\t \t \t \t "
30/* The following must each be of length 8 */
31#define OTRL_MESSAGE_TAG_V1 " \t \t \t "
32#define OTRL_MESSAGE_TAG_V2 " \t\t \t "
33
34/* The possible flags contained in a Data Message */
35#define OTRL_MSGFLAGS_IGNORE_UNREADABLE 0x01
36
37typedef unsigned int OtrlPolicy;
38
39#define OTRL_POLICY_ALLOW_V1 0x01
40#define OTRL_POLICY_ALLOW_V2 0x02
41#define OTRL_POLICY_REQUIRE_ENCRYPTION 0x04
42#define OTRL_POLICY_SEND_WHITESPACE_TAG 0x08
43#define OTRL_POLICY_WHITESPACE_START_AKE 0x10
44#define OTRL_POLICY_ERROR_START_AKE 0x20
45
46#define OTRL_POLICY_VERSION_MASK (OTRL_POLICY_ALLOW_V1 | OTRL_POLICY_ALLOW_V2)
47
48/* For v1 compatibility */
49#define OTRL_POLICY_NEVER 0x00
50#define OTRL_POLICY_OPPORTUNISTIC \
51 ( OTRL_POLICY_ALLOW_V1 | \
52 OTRL_POLICY_ALLOW_V2 | \
53 OTRL_POLICY_SEND_WHITESPACE_TAG | \
54 OTRL_POLICY_WHITESPACE_START_AKE | \
55 OTRL_POLICY_ERROR_START_AKE )
56#define OTRL_POLICY_MANUAL \
57 ( OTRL_POLICY_ALLOW_V1 | \
58 OTRL_POLICY_ALLOW_V2 )
59#define OTRL_POLICY_ALWAYS \
60 ( OTRL_POLICY_ALLOW_V1 | \
61 OTRL_POLICY_ALLOW_V2 | \
62 OTRL_POLICY_REQUIRE_ENCRYPTION | \
63 OTRL_POLICY_WHITESPACE_START_AKE | \
64 OTRL_POLICY_ERROR_START_AKE )
65#define OTRL_POLICY_DEFAULT OTRL_POLICY_OPPORTUNISTIC
66
67typedef enum {
68 OTRL_MSGTYPE_NOTOTR,
69 OTRL_MSGTYPE_TAGGEDPLAINTEXT,
70 OTRL_MSGTYPE_QUERY,
71 OTRL_MSGTYPE_DH_COMMIT,
72 OTRL_MSGTYPE_DH_KEY,
73 OTRL_MSGTYPE_REVEALSIG,
74 OTRL_MSGTYPE_SIGNATURE,
75 OTRL_MSGTYPE_V1_KEYEXCH,
76 OTRL_MSGTYPE_DATA,
77 OTRL_MSGTYPE_ERROR,
78 OTRL_MSGTYPE_UNKNOWN
79} OtrlMessageType;
80
81typedef enum {
82 OTRL_FRAGMENT_UNFRAGMENTED,
83 OTRL_FRAGMENT_INCOMPLETE,
84 OTRL_FRAGMENT_COMPLETE
85} OtrlFragmentResult;
86
87typedef enum {
88 OTRL_FRAGMENT_SEND_ALL,
89 OTRL_FRAGMENT_SEND_ALL_BUT_FIRST,
90 OTRL_FRAGMENT_SEND_ALL_BUT_LAST
91} OtrlFragmentPolicy;
92
93/* Initialize the OTR library. Pass the version of the API you are
94 * using. */
95void otrl_init(unsigned int ver_major, unsigned int ver_minor,
96 unsigned int ver_sub);
97
98/* Shortcut */
99#define OTRL_INIT do { \
100 otrl_init(OTRL_VERSION_MAJOR, OTRL_VERSION_MINOR, OTRL_VERSION_SUB); \
101 } while(0)
102
103/* Return a pointer to a static string containing the version number of
104 * the OTR library. */
105const char *otrl_version(void);
106
107/* Return a pointer to a newly-allocated OTR query message, customized
108 * with our name. The caller should free() the result when he's done
109 * with it. */
110char *otrl_proto_default_query_msg(const char *ourname, OtrlPolicy policy);
111
112/* Return the best version of OTR support by both sides, given an OTR
113 * Query Message and the local policy. */
114unsigned int otrl_proto_query_bestversion(const char *querymsg,
115 OtrlPolicy policy);
116
117/* Locate any whitespace tag in this message, and return the best
118 * version of OTR support on both sides. Set *starttagp and *endtagp to
119 * the start and end of the located tag, so that it can be snipped out. */
120unsigned int otrl_proto_whitespace_bestversion(const char *msg,
121 const char **starttagp, const char **endtagp, OtrlPolicy policy);
122
123/* Return the Message type of the given message. */
124OtrlMessageType otrl_proto_message_type(const char *message);
125
126/* Create an OTR Data message. Pass the plaintext as msg, and an
127 * optional chain of TLVs. A newly-allocated string will be returned in
128 * *encmessagep. */
129gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context,
130 const char *msg, const OtrlTLV *tlvs, unsigned char flags);
131
132/* Extract the flags from an otherwise unreadable Data Message. */
133gcry_error_t otrl_proto_data_read_flags(const char *datamsg,
134 unsigned char *flagsp);
135
136/* Accept an OTR Data Message in datamsg. Decrypt it and put the
137 * plaintext into *plaintextp, and any TLVs into tlvsp. Put any
138 * received flags into *flagsp (if non-NULL). */
139gcry_error_t otrl_proto_accept_data(char **plaintextp, OtrlTLV **tlvsp,
140 ConnContext *context, const char *datamsg, unsigned char *flagsp);
141
142/* free all the fragments we have collected */
143gcry_error_t otrl_free_fragments(ConnContext *context);
144
145/* Accumulate a potential fragment into the current context. */
146OtrlFragmentResult otrl_proto_fragment_accumulate(char **unfragmessagep,
147 ConnContext *context, const char *msg);
148
149gcry_error_t otrl_proto_fragment_create(int mms, int fragment_count,
150 char ***fragments, const char *message);
151
152void otrl_proto_fragment_free(char ***fragments, unsigned short arraylen);
153#endif
diff --git a/linden/indra/libotr/libotr-3.2.0/src/serial.h b/linden/indra/libotr/libotr-3.2.0/src/serial.h
new file mode 100755
index 0000000..edc3184
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/serial.h
@@ -0,0 +1,85 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef __SERIAL_H__
21#define __SERIAL_H__
22
23#undef DEBUG
24
25#ifdef DEBUG
26
27#include <stdio.h>
28
29#define debug_data(t,b,l) do { const unsigned char *data = (b); size_t i; \
30 fprintf(stderr, "%s: ", (t)); \
31 for(i=0;i<(l);++i) { \
32 fprintf(stderr, "%02x", data[i]); \
33 } \
34 fprintf(stderr, "\n"); \
35 } while(0)
36
37#define debug_int(t,b) do { const unsigned char *data = (b); \
38 unsigned int v = \
39 (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \
40 fprintf(stderr, "%s: %u (0x%x)\n", (t), v, v); \
41 } while(0)
42
43#else
44#define debug_data(t,b,l)
45#define debug_int(t,b)
46#endif
47
48#define write_int(x) do { \
49 bufp[0] = ((x) >> 24) & 0xff; \
50 bufp[1] = ((x) >> 16) & 0xff; \
51 bufp[2] = ((x) >> 8) & 0xff; \
52 bufp[3] = (x) & 0xff; \
53 bufp += 4; lenp -= 4; \
54 } while(0)
55
56#define write_mpi(x,nx,dx) do { \
57 write_int(nx); \
58 gcry_mpi_print(format, bufp, lenp, NULL, (x)); \
59 debug_data((dx), bufp, (nx)); \
60 bufp += (nx); lenp -= (nx); \
61 } while(0)
62
63#define require_len(l) do { \
64 if (lenp < (l)) goto invval; \
65 } while(0)
66
67#define read_int(x) do { \
68 require_len(4); \
69 (x) = (bufp[0] << 24) | (bufp[1] << 16) | (bufp[2] << 8) | bufp[3]; \
70 bufp += 4; lenp -= 4; \
71 } while(0)
72
73#define read_mpi(x) do { \
74 size_t mpilen; \
75 read_int(mpilen); \
76 if (mpilen) { \
77 require_len(mpilen); \
78 gcry_mpi_scan(&(x), GCRYMPI_FMT_USG, bufp, mpilen, NULL); \
79 } else { \
80 (x) = gcry_mpi_set_ui(NULL, 0); \
81 } \
82 bufp += mpilen; lenp -= mpilen; \
83 } while(0)
84
85#endif
diff --git a/linden/indra/libotr/libotr-3.2.0/src/sm.c b/linden/indra/libotr/libotr-3.2.0/src/sm.c
new file mode 100755
index 0000000..318b461
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/sm.c
@@ -0,0 +1,929 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/* system headers */
21#include <stdlib.h>
22#include <stdio.h>
23#include <sys/types.h>
24
25/* libgcrypt headers */
26#include <gcrypt.h>
27
28/* libotr headers */
29#include "sm.h"
30#include "serial.h"
31
32static const int SM_MSG1_LEN = 6;
33static const int SM_MSG2_LEN = 11;
34static const int SM_MSG3_LEN = 8;
35static const int SM_MSG4_LEN = 3;
36
37/* The modulus p */
38static const char* SM_MODULUS_S = "0x"
39 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
40 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
41 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
42 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
43 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
44 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
45 "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
46 "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF";
47/* The order of the group q = (p-1)/2 */
48static const char* SM_ORDER_S = "0x"
49 "7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68"
50 "948127044533E63A0105DF531D89CD9128A5043CC71A026E"
51 "F7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122"
52 "F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6"
53 "F71C35FDAD44CFD2D74F9208BE258FF324943328F6722D9E"
54 "E1003E5C50B1DF82CC6D241B0E2AE9CD348B1FD47E9267AF"
55 "C1B2AE91EE51D6CB0E3179AB1042A95DCF6A9483B84B4B36"
56 "B3861AA7255E4C0278BA36046511B993FFFFFFFFFFFFFFFF";
57static const char *SM_GENERATOR_S = "0x02";
58static const int SM_MOD_LEN_BITS = 1536;
59static const int SM_MOD_LEN_BYTES = 192;
60
61static gcry_mpi_t SM_MODULUS = NULL;
62static gcry_mpi_t SM_GENERATOR = NULL;
63static gcry_mpi_t SM_ORDER = NULL;
64static gcry_mpi_t SM_MODULUS_MINUS_2 = NULL;
65
66/*
67 * Call this once, at plugin load time. It sets up the modulus and
68 * generator MPIs.
69 */
70void otrl_sm_init(void)
71{
72 gcry_check_version(NULL);
73 gcry_mpi_scan(&SM_MODULUS, GCRYMPI_FMT_HEX, SM_MODULUS_S, 0, NULL);
74 gcry_mpi_scan(&SM_ORDER, GCRYMPI_FMT_HEX, SM_ORDER_S, 0, NULL);
75 gcry_mpi_scan(&SM_GENERATOR, GCRYMPI_FMT_HEX, SM_GENERATOR_S,
76 0, NULL);
77 SM_MODULUS_MINUS_2 = gcry_mpi_new(SM_MOD_LEN_BITS);
78 gcry_mpi_sub_ui(SM_MODULUS_MINUS_2, SM_MODULUS, 2);
79}
80
81/*
82 * Initialize the fields of a SM state.
83 */
84void otrl_sm_state_new(OtrlSMState *smst)
85{
86 smst->secret = NULL;
87 smst->x2 = NULL;
88 smst->x3 = NULL;
89 smst->g1 = NULL;
90 smst->g2 = NULL;
91 smst->g3 = NULL;
92 smst->g3o = NULL;
93 smst->p = NULL;
94 smst->q = NULL;
95 smst->pab = NULL;
96 smst->qab = NULL;
97 smst->nextExpected = OTRL_SMP_EXPECT1;
98 smst->received_question = 0;
99 smst->sm_prog_state = OTRL_SMP_PROG_OK;
100}
101
102/*
103 * Initialize the fields of a SM state. Called the first time that
104 * a user begins an SMP session.
105 */
106void otrl_sm_state_init(OtrlSMState *smst)
107{
108 otrl_sm_state_free(smst);
109 smst->secret = gcry_mpi_new(SM_MOD_LEN_BITS);
110 smst->x2 = NULL;
111 smst->x3 = NULL;
112 smst->g1 = gcry_mpi_copy(SM_GENERATOR);
113 smst->g2 = gcry_mpi_new(SM_MOD_LEN_BITS);
114 smst->g3 = gcry_mpi_new(SM_MOD_LEN_BITS);
115 smst->g3o = gcry_mpi_new(SM_MOD_LEN_BITS);
116 smst->p = gcry_mpi_new(SM_MOD_LEN_BITS);
117 smst->q = gcry_mpi_new(SM_MOD_LEN_BITS);
118 smst->pab = gcry_mpi_new(SM_MOD_LEN_BITS);
119 smst->qab = gcry_mpi_new(SM_MOD_LEN_BITS);
120 smst->received_question = 0;
121 smst->sm_prog_state = OTRL_SMP_PROG_OK;
122}
123
124/*
125 * Initialize the fields of a SM message1.
126 * [0] = g2a, [1] = c2, [2] = d2, [3] = g3a, [4] = c3, [5] = d3
127 */
128void otrl_sm_msg1_init(gcry_mpi_t **msg1)
129{
130 gcry_mpi_t *msg = malloc(SM_MSG1_LEN * sizeof(gcry_mpi_t));
131 msg[0] = gcry_mpi_new(SM_MOD_LEN_BITS);
132 msg[1] = NULL;
133 msg[2] = gcry_mpi_new(SM_MOD_LEN_BITS);
134 msg[3] = gcry_mpi_new(SM_MOD_LEN_BITS);
135 msg[4] = NULL;
136 msg[5] = gcry_mpi_new(SM_MOD_LEN_BITS);
137
138 *msg1 = msg;
139}
140
141/*
142 * Initialize the fields of a SM message2.
143 * [0] = g2b, [1] = c2, [2] = d2, [3] = g3b, [4] = c3, [5] = d3
144 * [6] = pb, [7] = qb, [8] = cp, [9] = d5, [10] = d6
145 */
146void otrl_sm_msg2_init(gcry_mpi_t **msg2)
147{
148 gcry_mpi_t *msg = malloc(SM_MSG2_LEN * sizeof(gcry_mpi_t));
149 msg[0] = gcry_mpi_new(SM_MOD_LEN_BITS);
150 msg[1] = NULL;
151 msg[2] = gcry_mpi_new(SM_MOD_LEN_BITS);
152 msg[3] = gcry_mpi_new(SM_MOD_LEN_BITS);
153 msg[4] = NULL;
154 msg[5] = gcry_mpi_new(SM_MOD_LEN_BITS);
155 msg[6] = gcry_mpi_new(SM_MOD_LEN_BITS);
156 msg[7] = gcry_mpi_new(SM_MOD_LEN_BITS);
157 msg[8] = NULL;
158 msg[9] = gcry_mpi_new(SM_MOD_LEN_BITS);
159 msg[10] = gcry_mpi_new(SM_MOD_LEN_BITS);
160
161 *msg2 = msg;
162}
163
164/*
165 * Initialize the fields of a SM message3.
166 * [0] = pa, [1] = qa, [2] = cp, [3] = d5, [4] = d6, [5] = ra,
167 * [6] = cr, [7] = d7
168 */
169void otrl_sm_msg3_init(gcry_mpi_t **msg3)
170{
171 gcry_mpi_t *msg = malloc(SM_MSG3_LEN * sizeof(gcry_mpi_t));
172 msg[0] = gcry_mpi_new(SM_MOD_LEN_BITS);
173 msg[1] = gcry_mpi_new(SM_MOD_LEN_BITS);
174 msg[2] = NULL;
175 msg[3] = gcry_mpi_new(SM_MOD_LEN_BITS);
176 msg[4] = gcry_mpi_new(SM_MOD_LEN_BITS);
177 msg[5] = gcry_mpi_new(SM_MOD_LEN_BITS);
178 msg[6] = NULL;
179 msg[7] = gcry_mpi_new(SM_MOD_LEN_BITS);
180
181 *msg3 = msg;
182}
183
184/*
185 * Initialize the fields of a SM message4.
186 * [0] = rb, [1] = cr, [2] = d7
187 */
188void otrl_sm_msg4_init(gcry_mpi_t **msg4)
189{
190 gcry_mpi_t *msg = malloc(SM_MSG4_LEN * sizeof(gcry_mpi_t));
191 msg[0] = gcry_mpi_new(SM_MOD_LEN_BITS);
192 msg[1] = NULL;
193 msg[2] = gcry_mpi_new(SM_MOD_LEN_BITS);
194
195 *msg4 = msg;
196}
197
198/*
199 * Deallocate the contents of a OtrlSMState (but not the OtrlSMState
200 * itself)
201 */
202void otrl_sm_state_free(OtrlSMState *smst)
203{
204 gcry_mpi_release(smst->secret);
205 gcry_mpi_release(smst->x2);
206 gcry_mpi_release(smst->x3);
207 gcry_mpi_release(smst->g1);
208 gcry_mpi_release(smst->g2);
209 gcry_mpi_release(smst->g3);
210 gcry_mpi_release(smst->g3o);
211 gcry_mpi_release(smst->p);
212 gcry_mpi_release(smst->q);
213 gcry_mpi_release(smst->pab);
214 gcry_mpi_release(smst->qab);
215 otrl_sm_state_new(smst);
216}
217
218/*
219 * Deallocate the contents of a message
220 */
221void otrl_sm_msg_free(gcry_mpi_t **message, int msglen)
222{
223 gcry_mpi_t *msg = *message;
224 int i;
225 for (i=0; i<msglen; i++) {
226 gcry_mpi_release(msg[i]);
227 }
228 free(msg);
229 *message = NULL;
230}
231
232static gcry_mpi_t randomExponent(void)
233{
234 unsigned char *secbuf = NULL;
235 gcry_mpi_t randexpon = NULL;
236
237 /* Generate a random exponent */
238 secbuf = gcry_random_bytes_secure(SM_MOD_LEN_BYTES, GCRY_STRONG_RANDOM);
239 gcry_mpi_scan(&randexpon, GCRYMPI_FMT_USG, secbuf, SM_MOD_LEN_BYTES, NULL);
240 gcry_free(secbuf);
241
242 return randexpon;
243}
244
245/*
246 * Hash one or two mpis. To hash only one mpi, b may be set to NULL.
247 */
248static gcry_error_t otrl_sm_hash(gcry_mpi_t* hash, int version,
249 const gcry_mpi_t a, const gcry_mpi_t b)
250{
251 unsigned char* input;
252 unsigned char output[SM_DIGEST_SIZE];
253 size_t sizea;
254 size_t sizeb;
255 size_t totalsize;
256 unsigned char* dataa;
257 unsigned char* datab;
258
259 gcry_mpi_aprint(GCRYMPI_FMT_USG, &dataa, &sizea, a);
260 totalsize = 1 + 4 + sizea;
261 if (b) {
262 gcry_mpi_aprint(GCRYMPI_FMT_USG, &datab, &sizeb, b);
263 totalsize += 4 + sizeb;
264 } else {
265 sizeb = 0;
266 }
267
268 input = malloc(totalsize);
269 input[0] = (unsigned char)version;
270 input[1] = (unsigned char)((sizea >> 24) & 0xFF);
271 input[2] = (unsigned char)((sizea >> 16) & 0xFF);
272 input[3] = (unsigned char)((sizea >> 8) & 0xFF);
273 input[4] = (unsigned char)(sizea & 0xFF);
274 memmove(input + 5, dataa, sizea);
275 if (b) {
276 input[5 + sizea] = (unsigned char)((sizeb >> 24) & 0xFF);
277 input[6 + sizea] = (unsigned char)((sizeb >> 16) & 0xFF);
278 input[7 + sizea] = (unsigned char)((sizeb >> 8) & 0xFF);
279 input[8 + sizea] = (unsigned char)(sizeb & 0xFF);
280 memmove(input + 9 + sizea, datab, sizeb);
281 }
282
283 gcry_md_hash_buffer(SM_HASH_ALGORITHM, output, input, totalsize);
284 gcry_mpi_scan(hash, GCRYMPI_FMT_USG, output, SM_DIGEST_SIZE, NULL);
285 free(input);
286 input = NULL;
287
288 /* free memory */
289 gcry_free(dataa);
290 if (b) gcry_free(datab);
291
292 return gcry_error(GPG_ERR_NO_ERROR);
293}
294
295/* This method should be passed a pointer to an uninitialized buffer,
296 * and a list of mpis with a list length. When returns, the buffer will
297 * point to newly-allocated memory (using malloc) containing a
298 * reversible serialization. */
299static gcry_error_t serialize_mpi_array(unsigned char **buffer, int *buflen,
300 unsigned int count, gcry_mpi_t *mpis)
301{
302 size_t totalsize = 0, lenp, nextsize;
303 unsigned int i, j;
304 size_t *list_sizes = malloc(count * sizeof(size_t));
305 unsigned char **tempbuffer = malloc(count * sizeof(unsigned char *));
306 unsigned char *bufp;
307
308 for (i=0; i<count; i++) {
309 gcry_mpi_aprint(GCRYMPI_FMT_USG, &(tempbuffer[i]), &(list_sizes[i]),
310 mpis[i]);
311 totalsize += list_sizes[i];
312 }
313
314 *buflen = (count+1)*4 + totalsize;
315 *buffer = malloc(*buflen * sizeof(char));
316
317 bufp = *buffer;
318 lenp = totalsize;
319
320 write_int(count);
321 for(i=0; i<count; i++)
322 {
323 nextsize = list_sizes[i];
324 write_int(nextsize);
325
326 for(j=0; j<nextsize; j++)
327 bufp[j] = tempbuffer[i][j];
328
329 bufp += nextsize;
330 lenp -= nextsize;
331 gcry_free(tempbuffer[i]);
332 }
333 free(tempbuffer);
334 free(list_sizes);
335
336 return gcry_error(GPG_ERR_NO_ERROR);
337}
338
339/* Takes a buffer containing serialized and concatenated mpis
340 * and converts it to an array of gcry_mpi_t structs.
341 * The buffer is assumed to consist of a 4-byte int containing the
342 * number of mpis in the array, followed by {size, data} pairs for
343 * each mpi. If malformed, method returns GCRY_ERROR_INV_VALUE */
344static gcry_error_t unserialize_mpi_array(gcry_mpi_t **mpis,
345 unsigned int expcount, const unsigned char *buffer, const int buflen)
346{
347 unsigned int i;
348 int lenp = buflen;
349 unsigned int thecount = 0;
350 const unsigned char* bufp = buffer;
351 *mpis = NULL;
352
353 read_int(thecount);
354 if (thecount != expcount) goto invval;
355
356 *mpis = malloc(thecount * sizeof(gcry_mpi_t));
357
358 for (i=0; i<thecount; i++) {
359 (*mpis)[i] = NULL;
360 }
361
362 for (i=0; i<thecount; i++) {
363 read_mpi((*mpis)[i]);
364 }
365
366 return gcry_error(GPG_ERR_NO_ERROR);
367
368invval:
369 if (*mpis) {
370 for (i=0; i<thecount; i++) {
371 gcry_mpi_release((*mpis)[i]);
372 }
373 free(*mpis);
374 *mpis = NULL;
375 }
376 return gcry_error(GPG_ERR_INV_VALUE);
377}
378
379/* Check that an MPI is in the right range to be a (non-unit) group
380 * element */
381static int check_group_elem(gcry_mpi_t g)
382{
383 if (gcry_mpi_cmp_ui(g, 2) < 0 ||
384 gcry_mpi_cmp(g, SM_MODULUS_MINUS_2) > 0) {
385 return 1;
386 }
387 return 0;
388}
389
390/* Check that an MPI is in the right range to be a (non-zero) exponent */
391static int check_expon(gcry_mpi_t x)
392{
393 if (gcry_mpi_cmp_ui(x, 1) < 0 ||
394 gcry_mpi_cmp(x, SM_ORDER) >= 0) {
395 return 1;
396 }
397 return 0;
398}
399
400/*
401 * Proof of knowledge of a discrete logarithm
402 */
403static gcry_error_t otrl_sm_proof_know_log(gcry_mpi_t *c, gcry_mpi_t *d, const gcry_mpi_t g, const gcry_mpi_t x, int version)
404{
405 gcry_mpi_t r = randomExponent();
406 gcry_mpi_t temp = gcry_mpi_new(SM_MOD_LEN_BITS);
407 gcry_mpi_powm(temp, g, r, SM_MODULUS);
408 otrl_sm_hash(c, version, temp, NULL);
409 gcry_mpi_mulm(temp, x, *c, SM_ORDER);
410 gcry_mpi_subm(*d, r, temp, SM_ORDER);
411 gcry_mpi_release(temp);
412 gcry_mpi_release(r);
413
414 return gcry_error(GPG_ERR_NO_ERROR);
415}
416
417/*
418 * Verify a proof of knowledge of a discrete logarithm. Checks that c = h(g^d x^c)
419 */
420static int otrl_sm_check_know_log(const gcry_mpi_t c, const gcry_mpi_t d, const gcry_mpi_t g, const gcry_mpi_t x, int version)
421{
422 int comp;
423
424 gcry_mpi_t gd = gcry_mpi_new(SM_MOD_LEN_BITS); /* g^d */
425 gcry_mpi_t xc = gcry_mpi_new(SM_MOD_LEN_BITS); /* x^c */
426 gcry_mpi_t gdxc = gcry_mpi_new(SM_MOD_LEN_BITS); /* (g^d x^c) */
427 gcry_mpi_t hgdxc = NULL; /* h(g^d x^c) */
428
429 gcry_mpi_powm(gd, g, d, SM_MODULUS);
430 gcry_mpi_powm(xc, x, c, SM_MODULUS);
431 gcry_mpi_mulm(gdxc, gd, xc, SM_MODULUS);
432 otrl_sm_hash(&hgdxc, version, gdxc, NULL);
433
434 comp = gcry_mpi_cmp(hgdxc, c);
435 gcry_mpi_release(gd);
436 gcry_mpi_release(xc);
437 gcry_mpi_release(gdxc);
438 gcry_mpi_release(hgdxc);
439
440 return comp;
441}
442
443/*
444 * Proof of knowledge of coordinates with first components being equal
445 */
446static gcry_error_t otrl_sm_proof_equal_coords(gcry_mpi_t *c, gcry_mpi_t *d1, gcry_mpi_t *d2, const OtrlSMState *state, const gcry_mpi_t r, int version)
447{
448 gcry_mpi_t r1 = randomExponent();
449 gcry_mpi_t r2 = randomExponent();
450 gcry_mpi_t temp1 = gcry_mpi_new(SM_MOD_LEN_BITS);
451 gcry_mpi_t temp2 = gcry_mpi_new(SM_MOD_LEN_BITS);
452
453 /* Compute the value of c, as c = h(g3^r1, g1^r1 g2^r2) */
454 gcry_mpi_powm(temp1, state->g1, r1, SM_MODULUS);
455 gcry_mpi_powm(temp2, state->g2, r2, SM_MODULUS);
456 gcry_mpi_mulm(temp2, temp1, temp2, SM_MODULUS);
457 gcry_mpi_powm(temp1, state->g3, r1, SM_MODULUS);
458 otrl_sm_hash(c, version, temp1, temp2);
459
460 /* Compute the d values, as d1 = r1 - r c, d2 = r2 - secret c */
461 gcry_mpi_mulm(temp1, r, *c, SM_ORDER);
462 gcry_mpi_subm(*d1, r1, temp1, SM_ORDER);
463
464 gcry_mpi_mulm(temp1, state->secret, *c, SM_ORDER);
465 gcry_mpi_subm(*d2, r2, temp1, SM_ORDER);
466
467 /* All clear */
468 gcry_mpi_release(r1);
469 gcry_mpi_release(r2);
470 gcry_mpi_release(temp1);
471 gcry_mpi_release(temp2);
472 return gcry_error(GPG_ERR_NO_ERROR);
473}
474
475/*
476 * Verify a proof of knowledge of coordinates with first components being equal
477 */
478static gcry_error_t otrl_sm_check_equal_coords(const gcry_mpi_t c, const gcry_mpi_t d1, const gcry_mpi_t d2, const gcry_mpi_t p, const gcry_mpi_t q, const OtrlSMState *state, int version)
479{
480 int comp;
481
482 gcry_mpi_t temp1 = gcry_mpi_new(SM_MOD_LEN_BITS);
483 gcry_mpi_t temp2 = gcry_mpi_new(SM_MOD_LEN_BITS);
484 gcry_mpi_t temp3 = gcry_mpi_new(SM_MOD_LEN_BITS);
485 gcry_mpi_t cprime = NULL;
486
487 /* To verify, we test that hash(g3^d1 * p^c, g1^d1 * g2^d2 * q^c) = c
488 * If indeed c = hash(g3^r1, g1^r1 g2^r2), d1 = r1 - r*c,
489 * d2 = r2 - secret*c. And if indeed p = g3^r, q = g1^r * g2^secret
490 * Then we should have that:
491 * hash(g3^d1 * p^c, g1^d1 * g2^d2 * q^c)
492 * = hash(g3^(r1 - r*c + r*c), g1^(r1 - r*c + q*c) *
493 * g2^(r2 - secret*c + secret*c))
494 * = hash(g3^r1, g1^r1 g2^r2)
495 * = c
496 */
497 gcry_mpi_powm(temp2, state->g3, d1, SM_MODULUS);
498 gcry_mpi_powm(temp3, p, c, SM_MODULUS);
499 gcry_mpi_mulm(temp1, temp2, temp3, SM_MODULUS);
500
501 gcry_mpi_powm(temp2, state->g1, d1, SM_MODULUS);
502 gcry_mpi_powm(temp3, state->g2, d2, SM_MODULUS);
503 gcry_mpi_mulm(temp2, temp2, temp3, SM_MODULUS);
504 gcry_mpi_powm(temp3, q, c, SM_MODULUS);
505 gcry_mpi_mulm(temp2, temp3, temp2, SM_MODULUS);
506
507 otrl_sm_hash(&cprime, version, temp1, temp2);
508
509 comp = gcry_mpi_cmp(c, cprime);
510 gcry_mpi_release(temp1);
511 gcry_mpi_release(temp2);
512 gcry_mpi_release(temp3);
513 gcry_mpi_release(cprime);
514
515 return comp;
516}
517
518/*
519 * Proof of knowledge of logs with exponents being equal
520 */
521static gcry_error_t otrl_sm_proof_equal_logs(gcry_mpi_t *c, gcry_mpi_t *d, OtrlSMState *state, int version)
522{
523 gcry_mpi_t r = randomExponent();
524 gcry_mpi_t temp1 = gcry_mpi_new(SM_MOD_LEN_BITS);
525 gcry_mpi_t temp2 = gcry_mpi_new(SM_MOD_LEN_BITS);
526
527 /* Compute the value of c, as c = h(g1^r, (Qa/Qb)^r) */
528 gcry_mpi_powm(temp1, state->g1, r, SM_MODULUS);
529 gcry_mpi_powm(temp2, state->qab, r, SM_MODULUS);
530 otrl_sm_hash(c, version, temp1, temp2);
531
532 /* Compute the d values, as d = r - x3 c */
533 gcry_mpi_mulm(temp1, state->x3, *c, SM_ORDER);
534 gcry_mpi_subm(*d, r, temp1, SM_ORDER);
535
536 /* All clear */
537 gcry_mpi_release(r);
538 gcry_mpi_release(temp1);
539 gcry_mpi_release(temp2);
540 return gcry_error(GPG_ERR_NO_ERROR);
541}
542
543/*
544 * Verify a proof of knowledge of logs with exponents being equal
545 */
546static gcry_error_t otrl_sm_check_equal_logs(const gcry_mpi_t c, const gcry_mpi_t d, const gcry_mpi_t r, const OtrlSMState *state, int version)
547{
548 int comp;
549
550 gcry_mpi_t temp1 = gcry_mpi_new(SM_MOD_LEN_BITS);
551 gcry_mpi_t temp2 = gcry_mpi_new(SM_MOD_LEN_BITS);
552 gcry_mpi_t temp3 = gcry_mpi_new(SM_MOD_LEN_BITS);
553 gcry_mpi_t cprime = NULL;
554
555 /* Here, we recall the exponents used to create g3.
556 * If we have previously seen g3o = g1^x where x is unknown
557 * during the DH exchange to produce g3, then we may proceed with:
558 *
559 * To verify, we test that hash(g1^d * g3o^c, qab^d * r^c) = c
560 * If indeed c = hash(g1^r1, qab^r1), d = r1- x * c
561 * And if indeed r = qab^x
562 * Then we should have that:
563 * hash(g1^d * g3o^c, qab^d r^c)
564 * = hash(g1^(r1 - x*c + x*c), qab^(r1 - x*c + x*c))
565 * = hash(g1^r1, qab^r1)
566 * = c
567 */
568 gcry_mpi_powm(temp2, state->g1, d, SM_MODULUS);
569 gcry_mpi_powm(temp3, state->g3o, c, SM_MODULUS);
570 gcry_mpi_mulm(temp1, temp2, temp3, SM_MODULUS);
571
572 gcry_mpi_powm(temp3, state->qab, d, SM_MODULUS);
573 gcry_mpi_powm(temp2, r, c, SM_MODULUS);
574 gcry_mpi_mulm(temp2, temp3, temp2, SM_MODULUS);
575
576 otrl_sm_hash(&cprime, version, temp1, temp2);
577
578 comp = gcry_mpi_cmp(c, cprime);
579 gcry_mpi_release(temp1);
580 gcry_mpi_release(temp2);
581 gcry_mpi_release(temp3);
582 gcry_mpi_release(cprime);
583
584 return comp;
585}
586
587/* Create first message in SMP exchange. Input is Alice's secret value
588 * which this protocol aims to compare to Bob's. Output is a serialized
589 * mpi array whose elements correspond to the following:
590 * [0] = g2a, Alice's half of DH exchange to determine g2
591 * [1] = c2, [2] = d2, Alice's ZK proof of knowledge of g2a exponent
592 * [3] = g3a, Alice's half of DH exchange to determine g3
593 * [4] = c3, [5] = d3, Alice's ZK proof of knowledge of g3a exponent */
594gcry_error_t otrl_sm_step1(OtrlSMAliceState *astate,
595 const unsigned char* secret, int secretlen,
596 unsigned char** output, int* outputlen)
597{
598 /* Initialize the sm state or update the secret */
599 gcry_mpi_t secret_mpi = NULL;
600 gcry_mpi_t *msg1;
601
602 *output = NULL;
603 *outputlen = 0;
604
605 gcry_mpi_scan(&secret_mpi, GCRYMPI_FMT_USG, secret, secretlen, NULL);
606
607 if (! astate->g1) {
608 otrl_sm_state_init(astate);
609 }
610 gcry_mpi_set(astate->secret, secret_mpi);
611 gcry_mpi_release(secret_mpi);
612 astate->received_question = 0;
613
614 otrl_sm_msg1_init(&msg1);
615
616 astate->x2 = randomExponent();
617 astate->x3 = randomExponent();
618
619 gcry_mpi_powm(msg1[0], astate->g1, astate->x2, SM_MODULUS);
620 otrl_sm_proof_know_log(&(msg1[1]), &(msg1[2]), astate->g1, astate->x2, 1);
621
622 gcry_mpi_powm(msg1[3], astate->g1, astate->x3, SM_MODULUS);
623 otrl_sm_proof_know_log(&(msg1[4]), &(msg1[5]), astate->g1, astate->x3, 2);
624
625 serialize_mpi_array(output, outputlen, SM_MSG1_LEN, msg1);
626 otrl_sm_msg_free(&msg1, SM_MSG1_LEN);
627 astate->sm_prog_state = OTRL_SMP_PROG_OK;
628 return gcry_error(GPG_ERR_NO_ERROR);
629}
630
631/* Receive the first message in SMP exchange, which was generated by
632 * otrl_sm_step1. Input is saved until the user inputs their secret
633 * information. No output. */
634gcry_error_t otrl_sm_step2a(OtrlSMBobState *bstate, const unsigned char* input, const int inputlen, int received_question)
635{
636 gcry_mpi_t *msg1;
637 gcry_error_t err;
638
639 /* Initialize the sm state if needed */
640 if (! bstate->g1) {
641 otrl_sm_state_init(bstate);
642 }
643 bstate->received_question = received_question;
644 bstate->sm_prog_state = OTRL_SMP_PROG_CHEATED;
645
646 /* Read from input to find the mpis */
647 err = unserialize_mpi_array(&msg1, SM_MSG1_LEN, input, inputlen);
648
649 if (err != gcry_error(GPG_ERR_NO_ERROR)) return err;
650
651 if (check_group_elem(msg1[0]) || check_expon(msg1[2]) ||
652 check_group_elem(msg1[3]) || check_expon(msg1[5])) {
653 return gcry_error(GPG_ERR_INV_VALUE);
654 }
655
656 /* Store Alice's g3a value for later in the protocol */
657 gcry_mpi_set(bstate->g3o, msg1[3]);
658
659 /* Verify Alice's proofs */
660 if (otrl_sm_check_know_log(msg1[1], msg1[2], bstate->g1, msg1[0], 1) ||
661 otrl_sm_check_know_log(msg1[4], msg1[5], bstate->g1, msg1[3], 2)) {
662 return gcry_error(GPG_ERR_INV_VALUE);
663 }
664
665 /* Create Bob's half of the generators g2 and g3 */
666 bstate->x2 = randomExponent();
667 bstate->x3 = randomExponent();
668
669 /* Combine the two halves from Bob and Alice and determine g2 and g3 */
670 gcry_mpi_powm(bstate->g2, msg1[0], bstate->x2, SM_MODULUS);
671 gcry_mpi_powm(bstate->g3, msg1[3], bstate->x3, SM_MODULUS);
672
673 bstate->sm_prog_state = OTRL_SMP_PROG_OK;
674 return gcry_error(GPG_ERR_NO_ERROR);
675}
676
677/* Create second message in SMP exchange. Input is Bob's secret value.
678 * Information from earlier steps in the exchange is taken from Bob's
679 * state. Output is a serialized mpi array whose elements correspond
680 * to the following:
681 * [0] = g2b, Bob's half of DH exchange to determine g2
682 * [1] = c2, [2] = d2, Bob's ZK proof of knowledge of g2b exponent
683 * [3] = g3b, Bob's half of DH exchange to determine g3
684 * [4] = c3, [5] = d3, Bob's ZK proof of knowledge of g3b exponent
685 * [6] = pb, [7] = qb, Bob's halves of the (Pa/Pb) and (Qa/Qb) values
686 * [8] = cp, [9] = d5, [10] = d6, Bob's ZK proof that pb, qb formed correctly */
687gcry_error_t otrl_sm_step2b(OtrlSMBobState *bstate, const unsigned char* secret, int secretlen, unsigned char **output, int* outputlen)
688{
689 /* Convert the given secret to the proper form and store it */
690 gcry_mpi_t r, qb1, qb2;
691 gcry_mpi_t *msg2;
692 gcry_mpi_t secret_mpi = NULL;
693
694 *output = NULL;
695 *outputlen = 0;
696
697 gcry_mpi_scan(&secret_mpi, GCRYMPI_FMT_USG, secret, secretlen, NULL);
698 gcry_mpi_set(bstate->secret, secret_mpi);
699 gcry_mpi_release(secret_mpi);
700
701 otrl_sm_msg2_init(&msg2);
702
703 gcry_mpi_powm(msg2[0], bstate->g1, bstate->x2, SM_MODULUS);
704 otrl_sm_proof_know_log(&(msg2[1]), &(msg2[2]), bstate->g1, bstate->x2, 3);
705
706 gcry_mpi_powm(msg2[3], bstate->g1, bstate->x3, SM_MODULUS);
707 otrl_sm_proof_know_log(&(msg2[4]), &(msg2[5]), bstate->g1, bstate->x3, 4);
708
709 /* Calculate P and Q values for Bob */
710 r = randomExponent();
711 qb1 = gcry_mpi_new(SM_MOD_LEN_BITS);
712 qb2 = gcry_mpi_new(SM_MOD_LEN_BITS);
713 gcry_mpi_powm(bstate->p, bstate->g3, r, SM_MODULUS);
714 gcry_mpi_set(msg2[6], bstate->p);
715 gcry_mpi_powm(qb1, bstate->g1, r, SM_MODULUS);
716 gcry_mpi_powm(qb2, bstate->g2, bstate->secret, SM_MODULUS);
717 gcry_mpi_mulm(bstate->q, qb1, qb2, SM_MODULUS);
718 gcry_mpi_set(msg2[7], bstate->q);
719
720 otrl_sm_proof_equal_coords(&(msg2[8]), &(msg2[9]), &(msg2[10]), bstate, r, 5);
721
722 /* Convert to serialized form */
723 serialize_mpi_array(output, outputlen, SM_MSG2_LEN, msg2);
724
725 /* Free up memory for unserialized and intermediate values */
726 gcry_mpi_release(r);
727 gcry_mpi_release(qb1);
728 gcry_mpi_release(qb2);
729 otrl_sm_msg_free(&msg2, SM_MSG2_LEN);
730
731 return gcry_error(GPG_ERR_NO_ERROR);
732}
733
734/* Create third message in SMP exchange. Input is a message generated
735 * by otrl_sm_step2b. Output is a serialized mpi array whose elements
736 * correspond to the following:
737 * [0] = pa, [1] = qa, Alice's halves of the (Pa/Pb) and (Qa/Qb) values
738 * [2] = cp, [3] = d5, [4] = d6, Alice's ZK proof that pa, qa formed correctly
739 * [5] = ra, calculated as (Qa/Qb)^x3 where x3 is the exponent used in g3a
740 * [6] = cr, [7] = d7, Alice's ZK proof that ra is formed correctly */
741gcry_error_t otrl_sm_step3(OtrlSMAliceState *astate, const unsigned char* input, const int inputlen, unsigned char **output, int* outputlen)
742{
743 /* Read from input to find the mpis */
744 gcry_mpi_t r, qa1, qa2, inv;
745 gcry_mpi_t *msg2;
746 gcry_mpi_t *msg3;
747 gcry_error_t err;
748
749 *output = NULL;
750 *outputlen = 0;
751 astate->sm_prog_state = OTRL_SMP_PROG_CHEATED;
752
753 err = unserialize_mpi_array(&msg2, SM_MSG2_LEN, input, inputlen);
754 if (err != gcry_error(GPG_ERR_NO_ERROR)) return err;
755
756 if (check_group_elem(msg2[0]) || check_group_elem(msg2[3]) ||
757 check_group_elem(msg2[6]) || check_group_elem(msg2[7]) ||
758 check_expon(msg2[2]) || check_expon(msg2[5]) ||
759 check_expon(msg2[9]) || check_expon(msg2[10])) {
760 return gcry_error(GPG_ERR_INV_VALUE);
761 }
762
763 otrl_sm_msg3_init(&msg3);
764
765 /* Store Bob's g3a value for later in the protocol */
766 gcry_mpi_set(astate->g3o, msg2[3]);
767
768 /* Verify Bob's knowledge of discreet log proofs */
769 if (otrl_sm_check_know_log(msg2[1], msg2[2], astate->g1, msg2[0], 3) ||
770 otrl_sm_check_know_log(msg2[4], msg2[5], astate->g1, msg2[3], 4)) {
771 return gcry_error(GPG_ERR_INV_VALUE);
772 }
773
774 /* Combine the two halves from Bob and Alice and determine g2 and g3 */
775 gcry_mpi_powm(astate->g2, msg2[0], astate->x2, SM_MODULUS);
776 gcry_mpi_powm(astate->g3, msg2[3], astate->x3, SM_MODULUS);
777
778 /* Verify Bob's coordinate equality proof */
779 if (otrl_sm_check_equal_coords(msg2[8], msg2[9], msg2[10], msg2[6], msg2[7], astate, 5))
780 return gcry_error(GPG_ERR_INV_VALUE);
781
782 /* Calculate P and Q values for Alice */
783 r = randomExponent();
784 qa1 = gcry_mpi_new(SM_MOD_LEN_BITS);
785 qa2 = gcry_mpi_new(SM_MOD_LEN_BITS);
786 gcry_mpi_powm(astate->p, astate->g3, r, SM_MODULUS);
787 gcry_mpi_set(msg3[0], astate->p);
788 gcry_mpi_powm(qa1, astate->g1, r, SM_MODULUS);
789 gcry_mpi_powm(qa2, astate->g2, astate->secret, SM_MODULUS);
790 gcry_mpi_mulm(astate->q, qa1, qa2, SM_MODULUS);
791 gcry_mpi_set(msg3[1], astate->q);
792
793 otrl_sm_proof_equal_coords(&(msg3[2]), &(msg3[3]), &(msg3[4]), astate, r, 6);
794
795 /* Calculate Ra and proof */
796 inv = gcry_mpi_new(SM_MOD_LEN_BITS);
797 gcry_mpi_invm(inv, msg2[6], SM_MODULUS);
798 gcry_mpi_mulm(astate->pab, astate->p, inv, SM_MODULUS);
799 gcry_mpi_invm(inv, msg2[7], SM_MODULUS);
800 gcry_mpi_mulm(astate->qab, astate->q, inv, SM_MODULUS);
801 gcry_mpi_powm(msg3[5], astate->qab, astate->x3, SM_MODULUS);
802 otrl_sm_proof_equal_logs(&(msg3[6]), &(msg3[7]), astate, 7);
803
804 serialize_mpi_array(output, outputlen, SM_MSG3_LEN, msg3);
805 otrl_sm_msg_free(&msg2, SM_MSG2_LEN);
806 otrl_sm_msg_free(&msg3, SM_MSG3_LEN);
807
808 gcry_mpi_release(r);
809 gcry_mpi_release(qa1);
810 gcry_mpi_release(qa2);
811 gcry_mpi_release(inv);
812
813 astate->sm_prog_state = OTRL_SMP_PROG_OK;
814 return gcry_error(GPG_ERR_NO_ERROR);
815}
816
817/* Create final message in SMP exchange. Input is a message generated
818 * by otrl_sm_step3. Output is a serialized mpi array whose elements
819 * correspond to the following:
820 * [0] = rb, calculated as (Qa/Qb)^x3 where x3 is the exponent used in g3b
821 * [1] = cr, [2] = d7, Bob's ZK proof that rb is formed correctly
822 * This method also checks if Alice and Bob's secrets were the same. If
823 * so, it returns NO_ERROR. If the secrets differ, an INV_VALUE error is
824 * returned instead. */
825gcry_error_t otrl_sm_step4(OtrlSMBobState *bstate, const unsigned char* input, const int inputlen, unsigned char **output, int* outputlen)
826{
827 /* Read from input to find the mpis */
828 int comp;
829 gcry_mpi_t inv, rab;
830 gcry_mpi_t *msg3;
831 gcry_mpi_t *msg4;
832 gcry_error_t err;
833 err = unserialize_mpi_array(&msg3, SM_MSG3_LEN, input, inputlen);
834
835 *output = NULL;
836 *outputlen = 0;
837 bstate->sm_prog_state = OTRL_SMP_PROG_CHEATED;
838
839 if (err != gcry_error(GPG_ERR_NO_ERROR)) return err;
840
841 otrl_sm_msg4_init(&msg4);
842
843 if (check_group_elem(msg3[0]) || check_group_elem(msg3[1]) ||
844 check_group_elem(msg3[5]) || check_expon(msg3[3]) ||
845 check_expon(msg3[4]) || check_expon(msg3[7])) {
846 return gcry_error(GPG_ERR_INV_VALUE);
847 }
848
849 /* Verify Alice's coordinate equality proof */
850 if (otrl_sm_check_equal_coords(msg3[2], msg3[3], msg3[4], msg3[0], msg3[1], bstate, 6))
851 return gcry_error(GPG_ERR_INV_VALUE);
852
853 /* Find Pa/Pb and Qa/Qb */
854 inv = gcry_mpi_new(SM_MOD_LEN_BITS);
855 gcry_mpi_invm(inv, bstate->p, SM_MODULUS);
856 gcry_mpi_mulm(bstate->pab, msg3[0], inv, SM_MODULUS);
857 gcry_mpi_invm(inv, bstate->q, SM_MODULUS);
858 gcry_mpi_mulm(bstate->qab, msg3[1], inv, SM_MODULUS);
859
860 /* Verify Alice's log equality proof */
861 if (otrl_sm_check_equal_logs(msg3[6], msg3[7], msg3[5], bstate, 7))
862 return gcry_error(GPG_ERR_INV_VALUE);
863
864 /* Calculate Rb and proof */
865 gcry_mpi_powm(msg4[0], bstate->qab, bstate->x3, SM_MODULUS);
866 otrl_sm_proof_equal_logs(&(msg4[1]), &(msg4[2]), bstate, 8);
867
868 serialize_mpi_array(output, outputlen, SM_MSG4_LEN, msg4);
869
870 /* Calculate Rab and verify that secrets match */
871 rab = gcry_mpi_new(SM_MOD_LEN_BITS);
872 gcry_mpi_powm(rab, msg3[5], bstate->x3, SM_MODULUS);
873 comp = gcry_mpi_cmp(rab, bstate->pab);
874
875 /* Clean up everything allocated in this step */
876 otrl_sm_msg_free(&msg3, SM_MSG3_LEN);
877 otrl_sm_msg_free(&msg4, SM_MSG4_LEN);
878 gcry_mpi_release(rab);
879 gcry_mpi_release(inv);
880
881 bstate->sm_prog_state = comp ? OTRL_SMP_PROG_FAILED :
882 OTRL_SMP_PROG_SUCCEEDED;
883
884 if (comp)
885 return gcry_error(GPG_ERR_INV_VALUE);
886 else
887 return gcry_error(GPG_ERR_NO_ERROR);
888}
889
890/* Receives the final SMP message, which was generated in otrl_sm_step.
891 * This method checks if Alice and Bob's secrets were the same. If
892 * so, it returns NO_ERROR. If the secrets differ, an INV_VALUE error is
893 * returned instead. */
894gcry_error_t otrl_sm_step5(OtrlSMAliceState *astate, const unsigned char* input, const int inputlen)
895{
896 /* Read from input to find the mpis */
897 int comp;
898 gcry_mpi_t rab;
899 gcry_mpi_t *msg4;
900 gcry_error_t err;
901 err = unserialize_mpi_array(&msg4, SM_MSG4_LEN, input, inputlen);
902 astate->sm_prog_state = OTRL_SMP_PROG_CHEATED;
903
904 if (err != gcry_error(GPG_ERR_NO_ERROR)) return err;
905
906 if (check_group_elem(msg4[0]) || check_expon(msg4[2])) {
907 return gcry_error(GPG_ERR_INV_VALUE);
908 }
909
910 /* Verify Bob's log equality proof */
911 if (otrl_sm_check_equal_logs(msg4[1], msg4[2], msg4[0], astate, 8))
912 return gcry_error(GPG_ERR_INV_VALUE);
913
914 /* Calculate Rab and verify that secrets match */
915 rab = gcry_mpi_new(SM_MOD_LEN_BITS);
916 gcry_mpi_powm(rab, msg4[0], astate->x3, SM_MODULUS);
917
918 comp = gcry_mpi_cmp(rab, astate->pab);
919 gcry_mpi_release(rab);
920 otrl_sm_msg_free(&msg4, SM_MSG4_LEN);
921
922 astate->sm_prog_state = comp ? OTRL_SMP_PROG_FAILED :
923 OTRL_SMP_PROG_SUCCEEDED;
924
925 if (comp)
926 return gcry_error(GPG_ERR_INV_VALUE);
927 else
928 return gcry_error(GPG_ERR_NO_ERROR);
929}
diff --git a/linden/indra/libotr/libotr-3.2.0/src/sm.h b/linden/indra/libotr/libotr-3.2.0/src/sm.h
new file mode 100755
index 0000000..2e94f07
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/sm.h
@@ -0,0 +1,83 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef __SM_H__
21#define __SM_H__
22
23#include <gcrypt.h>
24
25#define SM_HASH_ALGORITHM GCRY_MD_SHA256
26#define SM_DIGEST_SIZE 32
27
28typedef enum {
29 OTRL_SMP_EXPECT1,
30 OTRL_SMP_EXPECT2,
31 OTRL_SMP_EXPECT3,
32 OTRL_SMP_EXPECT4,
33 OTRL_SMP_EXPECT5
34} NextExpectedSMP;
35
36typedef enum {
37 OTRL_SMP_PROG_OK = 0, /* All is going fine so far */
38 OTRL_SMP_PROG_CHEATED = -2, /* Some verification failed */
39 OTRL_SMP_PROG_FAILED = -1, /* The secrets didn't match */
40 OTRL_SMP_PROG_SUCCEEDED = 1 /* The SMP completed successfully */
41} OtrlSMProgState;
42
43typedef struct {
44 gcry_mpi_t secret, x2, x3, g1, g2, g3, g3o, p, q, pab, qab;
45 NextExpectedSMP nextExpected;
46 int received_question; /* 1 if we received a question in an SMP1Q TLV */
47 OtrlSMProgState sm_prog_state;
48} OtrlSMState;
49
50typedef OtrlSMState OtrlSMAliceState;
51typedef OtrlSMState OtrlSMBobState;
52
53/*
54 * Call this once, at plugin load time. It sets up the modulus and
55 * generator MPIs.
56 */
57void otrl_sm_init(void);
58
59/*
60 * Initialize the fields of a SM state.
61 */
62void otrl_sm_state_new(OtrlSMState *smst);
63
64/*
65 * Initialize the fields of a SM state. Called the first time that
66 * a user begins an SMP session.
67 */
68void otrl_sm_state_init(OtrlSMState *smst);
69
70/*
71 * Deallocate the contents of a OtrlSMState (but not the OtrlSMState
72 * itself)
73 */
74void otrl_sm_state_free(OtrlSMState *smst);
75
76gcry_error_t otrl_sm_step1(OtrlSMAliceState *astate, const unsigned char* secret, int secretlen, unsigned char** output, int* outputlen);
77gcry_error_t otrl_sm_step2a(OtrlSMBobState *bstate, const unsigned char* input, const int inputlen, int received_question);
78gcry_error_t otrl_sm_step2b(OtrlSMBobState *bstate, const unsigned char* secret, int secretlen, unsigned char **output, int* outputlen);
79gcry_error_t otrl_sm_step3(OtrlSMAliceState *astate, const unsigned char* input, const int inputlen, unsigned char **output, int* outputlen);
80gcry_error_t otrl_sm_step4(OtrlSMBobState *bstate, const unsigned char* input, const int inputlen, unsigned char **output, int* outputlen);
81gcry_error_t otrl_sm_step5(OtrlSMAliceState *astate, const unsigned char* input, const int inputlen);
82
83#endif
diff --git a/linden/indra/libotr/libotr-3.2.0/src/tlv.c b/linden/indra/libotr/libotr-3.2.0/src/tlv.c
new file mode 100755
index 0000000..0cea7b5
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/tlv.c
@@ -0,0 +1,108 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <stdlib.h>
21#include <string.h>
22#include <assert.h>
23
24#include "tlv.h"
25
26/* Make a single TLV, copying the supplied data */
27OtrlTLV *otrl_tlv_new(unsigned short type, unsigned short len,
28 const unsigned char *data)
29{
30 OtrlTLV *tlv = malloc(sizeof(OtrlTLV));
31 assert(tlv != NULL);
32 tlv->type = type;
33 tlv->len = len;
34 tlv->data = malloc(len + 1);
35 assert(tlv->data != NULL);
36 memmove(tlv->data, data, len);
37 tlv->data[tlv->len] = '\0';
38 tlv->next = NULL;
39 return tlv;
40}
41
42/* Construct a chain of TLVs from the given data */
43OtrlTLV *otrl_tlv_parse(const unsigned char *serialized, size_t seriallen)
44{
45 OtrlTLV *tlv = NULL;
46 OtrlTLV **tlvp = &tlv;
47 while (seriallen >= 4) {
48 unsigned short type = (serialized[0] << 8) + serialized[1];
49 unsigned short len = (serialized[2] << 8) + serialized[3];
50 serialized += 4; seriallen -=4;
51 if (seriallen < len) break;
52 *tlvp = otrl_tlv_new(type, len, serialized);
53 serialized += len;
54 seriallen -= len;
55 tlvp = &((*tlvp)->next);
56 }
57 return tlv;
58}
59
60/* Deallocate a chain of TLVs */
61void otrl_tlv_free(OtrlTLV *tlv)
62{
63 while (tlv) {
64 OtrlTLV *next = tlv->next;
65 free(tlv->data);
66 free(tlv);
67 tlv = next;
68 }
69}
70
71/* Find the serialized length of a chain of TLVs */
72size_t otrl_tlv_seriallen(const OtrlTLV *tlv)
73{
74 size_t totlen = 0;
75 while (tlv) {
76 totlen += tlv->len + 4;
77 tlv = tlv->next;
78 }
79 return totlen;
80}
81
82/* Serialize a chain of TLVs. The supplied buffer must already be large
83 * enough. */
84void otrl_tlv_serialize(unsigned char *buf, const OtrlTLV *tlv)
85{
86 while (tlv) {
87 buf[0] = (tlv->type >> 8) & 0xff;
88 buf[1] = tlv->type & 0xff;
89 buf[2] = (tlv->len >> 8) & 0xff;
90 buf[3] = tlv->len & 0xff;
91 buf += 4;
92 memmove(buf, tlv->data, tlv->len);
93 buf += tlv->len;
94 tlv = tlv->next;
95 }
96}
97
98/* Return the first TLV with the given type in the chain, or NULL if one
99 * isn't found. (The tlvs argument isn't const because the return type
100 * needs to be non-const.) */
101OtrlTLV *otrl_tlv_find(OtrlTLV *tlvs, unsigned short type)
102{
103 while (tlvs) {
104 if (tlvs->type == type) return tlvs;
105 tlvs = tlvs->next;
106 }
107 return NULL;
108}
diff --git a/linden/indra/libotr/libotr-3.2.0/src/tlv.h b/linden/indra/libotr/libotr-3.2.0/src/tlv.h
new file mode 100755
index 0000000..affe0d5
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/tlv.h
@@ -0,0 +1,70 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef __TLV_H__
21#define __TLV_H__
22
23typedef struct s_OtrlTLV {
24 unsigned short type;
25 unsigned short len;
26 unsigned char *data;
27 struct s_OtrlTLV *next;
28} OtrlTLV;
29
30/* TLV types */
31
32/* This is just padding for the encrypted message, and should be ignored. */
33#define OTRL_TLV_PADDING 0x0000
34
35/* The sender has thrown away his OTR session keys with you */
36#define OTRL_TLV_DISCONNECTED 0x0001
37
38/* The message contains a step in the Socialist Millionaires' Protocol. */
39#define OTRL_TLV_SMP1 0x0002
40#define OTRL_TLV_SMP2 0x0003
41#define OTRL_TLV_SMP3 0x0004
42#define OTRL_TLV_SMP4 0x0005
43#define OTRL_TLV_SMP_ABORT 0x0006
44/* Like OTRL_TLV_SMP1, but there's a question for the buddy at the
45 * beginning */
46#define OTRL_TLV_SMP1Q 0x0007
47
48/* Make a single TLV, copying the supplied data */
49OtrlTLV *otrl_tlv_new(unsigned short type, unsigned short len,
50 const unsigned char *data);
51
52/* Construct a chain of TLVs from the given data */
53OtrlTLV *otrl_tlv_parse(const unsigned char *serialized, size_t seriallen);
54
55/* Deallocate a chain of TLVs */
56void otrl_tlv_free(OtrlTLV *tlv);
57
58/* Find the serialized length of a chain of TLVs */
59size_t otrl_tlv_seriallen(const OtrlTLV *tlv);
60
61/* Serialize a chain of TLVs. The supplied buffer must already be large
62 * enough. */
63void otrl_tlv_serialize(unsigned char *buf, const OtrlTLV *tlv);
64
65/* Return the first TLV with the given type in the chain, or NULL if one
66 * isn't found. (The tlvs argument isn't const because the return type
67 * needs to be non-const.) */
68OtrlTLV *otrl_tlv_find(OtrlTLV *tlvs, unsigned short type);
69
70#endif
diff --git a/linden/indra/libotr/libotr-3.2.0/src/userstate.c b/linden/indra/libotr/libotr-3.2.0/src/userstate.c
new file mode 100755
index 0000000..6de95b8
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/userstate.c
@@ -0,0 +1,51 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/* system headers */
21#include <stdlib.h>
22
23/* libotr headers */
24#include "context.h"
25#include "privkey.h"
26#include "userstate.h"
27
28/* Create a new OtrlUserState. Most clients will only need one of
29 * these. A OtrlUserState encapsulates the list of known fingerprints
30 * and the list of private keys; if you have separate files for these
31 * things for (say) different users, use different OtrlUserStates. If
32 * you've got only one user, with multiple accounts all stored together
33 * in the same fingerprint store and privkey store files, use just one
34 * OtrlUserState. */
35OtrlUserState otrl_userstate_create(void)
36{
37 OtrlUserState us = malloc(sizeof(struct s_OtrlUserState));
38 if (!us) return NULL;
39 us->context_root = NULL;
40 us->privkey_root = NULL;
41
42 return us;
43}
44
45/* Free a OtrlUserState */
46void otrl_userstate_free(OtrlUserState us)
47{
48 otrl_context_forget_all(us);
49 otrl_privkey_forget_all(us);
50 free(us);
51}
diff --git a/linden/indra/libotr/libotr-3.2.0/src/userstate.h b/linden/indra/libotr/libotr-3.2.0/src/userstate.h
new file mode 100755
index 0000000..8525df0
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/userstate.h
@@ -0,0 +1,45 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef __USERSTATE_H__
21#define __USERSTATE_H__
22
23typedef struct s_OtrlUserState* OtrlUserState;
24
25#include "context.h"
26#include "privkey-t.h"
27
28struct s_OtrlUserState {
29 ConnContext *context_root;
30 OtrlPrivKey *privkey_root;
31};
32
33/* Create a new OtrlUserState. Most clients will only need one of
34 * these. A OtrlUserState encapsulates the list of known fingerprints
35 * and the list of private keys; if you have separate files for these
36 * things for (say) different users, use different OtrlUserStates. If
37 * you've got only one user, with multiple accounts all stored together
38 * in the same fingerprint store and privkey store files, use just one
39 * OtrlUserState. */
40OtrlUserState otrl_userstate_create(void);
41
42/* Free a OtrlUserState */
43void otrl_userstate_free(OtrlUserState us);
44
45#endif
diff --git a/linden/indra/libotr/libotr-3.2.0/src/version.h b/linden/indra/libotr/libotr-3.2.0/src/version.h
new file mode 100755
index 0000000..11cb586
--- /dev/null
+++ b/linden/indra/libotr/libotr-3.2.0/src/version.h
@@ -0,0 +1,29 @@
1/*
2 * Off-the-Record Messaging library
3 * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
4 * <otr@cypherpunks.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef __VERSION_H__
21#define __VERSION_H__
22
23#define OTRL_VERSION "3.2.0"
24
25#define OTRL_VERSION_MAJOR 3
26#define OTRL_VERSION_MINOR 2
27#define OTRL_VERSION_SUB 0
28
29#endif