aboutsummaryrefslogtreecommitdiffstats
path: root/kbx/keybox-search.c
diff options
context:
space:
mode:
Diffstat (limited to 'kbx/keybox-search.c')
-rw-r--r--kbx/keybox-search.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c
new file mode 100644
index 000000000..d2c61ff21
--- /dev/null
+++ b/kbx/keybox-search.c
@@ -0,0 +1,158 @@
+/* keybox-search.c - Search operations
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "keybox-defs.h"
+
+
+/****************
+ * Check whether the given fingerprint (20 bytes) is in the
+ * given keyblob. fpr is always 20 bytes.
+ * Return: 0 = found
+ * -1 = not found
+ other = error (fixme: do not always reurn gpgerr_general)
+ */
+int
+keybox_blob_has_fpr ( KEYBOXBLOB blob, const byte *fpr )
+{
+ ulong n, nkeys, keyinfolen;
+ const byte *p, *pend;
+ byte *buffer = blob->blob;
+ size_t buflen = blob->bloblen;
+
+ if ( buflen < 40 )
+ return GPGERR_GENERAL; /* blob too short */
+ n = get32( buffer );
+ if ( n > buflen )
+ return GPGERR_GENERAL; /* blob larger than announced length */
+ buflen = n; /* ignore trailing stuff */
+ pend = buffer + n - 1;
+
+ if ( buffer[4] != 2 )
+ return GPGERR_GENERAL; /* invalid blob type */
+ if ( buffer[5] != 1 )
+ return GPGERR_GENERAL; /* invalid blob format version */
+
+ nkeys = get16( buffer + 16 );
+ keyinfolen = get16( buffer + 18 );
+ p = buffer + 20;
+ for(n=0; n < nkeys; n++, p += keyinfolen ) {
+ if ( p+20 > pend )
+ return GPGERR_GENERAL; /* blob shorter than required */
+ if (!memcmp ( p, fpr, 20 ) )
+ return 0; /* found */
+ }
+ return -1;
+}
+
+/****************
+ * Check whether the given keyID (20 bytes) is in the
+ * given keyblob.
+ * Return: 0 = found
+ * -1 = not found
+ other = error (fixme: do not always return gpgerr_general)
+ */
+int
+keybox_blob_has_kid ( KEYBOXBLOB blob, const byte *keyidbuf, size_t keyidlen )
+{
+ ulong n, nkeys, keyinfolen, off;
+ const byte *p, *pend;
+ byte *buffer = blob->blob;
+ size_t buflen = blob->bloblen;
+
+ if ( buflen < 40 )
+ return GPGERR_GENERAL; /* blob too short */
+ n = get32( buffer );
+ if ( n > buflen )
+ return GPGERR_GENERAL; /* blob larger than announced length */
+ buflen = n; /* ignore trailing stuff */
+ pend = buffer + n - 1;
+
+ if ( buffer[4] != 2 )
+ return GPGERR_GENERAL; /* invalid blob type */
+ if ( buffer[5] != 1 )
+ return GPGERR_GENERAL; /* invalid blob format version */
+
+ nkeys = get16( buffer + 16 );
+ keyinfolen = get16( buffer + 18 );
+ p = buffer + 20;
+ for(n=0; n < nkeys; n++, p += keyinfolen ) {
+ if ( p+24 > pend )
+ return GPGERR_GENERAL; /* blob shorter than required */
+ off = get32 ( p + 20 );
+ if (keyidlen < 8 ) /* actually keyidlen may either be 4 or 8 */
+ off +=4;
+ if ( off+keyidlen > buflen )
+ return GPGERR_GENERAL; /* offset out of bounds */
+ if ( !memcmp ( buffer+off, keyidbuf, keyidlen ) )
+ return 0; /* found */
+ }
+ return -1;
+}
+
+
+
+int
+keybox_blob_has_uid ( KEYBOXBLOB blob,
+ int (*cmp)(const byte *, size_t, void *), void *opaque )
+{
+ ulong n, nuids, uidinfolen, off, len;
+ const byte *p, *pend;
+ byte *buffer = blob->blob;
+ size_t buflen = blob->bloblen;
+
+ if ( buflen < 40 )
+ return GPGERR_GENERAL; /* blob too short */
+ n = get32( buffer );
+ if ( n > buflen )
+ return GPGERR_GENERAL; /* blob larger than announced length */
+ buflen = n; /* ignore trailing stuff */
+ pend = buffer + n - 1;
+
+ if ( buffer[4] != 2 )
+ return GPGERR_GENERAL; /* invalid blob type */
+ if ( buffer[5] != 1 )
+ return GPGERR_GENERAL; /* invalid blob format version */
+
+ p = buffer + 20 + get16( buffer + 16 ) * get16( buffer + 18 );
+ if ( p+4 > pend )
+ return GPGERR_GENERAL; /* blob shorter than required */
+
+ nuids = get16( p ); p+= 2;
+ uidinfolen = get16( p ); p+=2;
+ for(n=0; n < nuids; n++, p += uidinfolen ) {
+ if ( p+8 > pend )
+ return GPGERR_GENERAL; /* blob shorter than required */
+ off = get32 ( p );
+ len = get32 ( p + 4 );
+ if ( off+len > buflen )
+ return GPGERR_GENERAL; /* offset out of bounds */
+ if ( (*cmp) ( buffer+off, len, opaque ) )
+ return 0; /* found */
+ }
+
+ return -1;
+}
+
+