21164880 pkg(5) elf file content hash should use gelf_sign_range(3ELF) s11u3-sru
authorsaurabh.vyas@oracle.com
Thu, 08 Dec 2016 03:40:55 +0530
branchs11u3-sru
changeset 3483 99004fc8ada4
parent 3482 2a84f1cb4808
child 3484 3ae629395c3b
21164880 pkg(5) elf file content hash should use gelf_sign_range(3ELF)
src/modules/actions/file.py
src/modules/elf.c
src/modules/elfextract.c
src/modules/elfextract.h
src/modules/flavor/elf.py
src/modules/server/transaction.py
src/tests/api/t_elf.py
--- a/src/modules/actions/file.py	Thu Dec 08 03:40:53 2016 +0530
+++ b/src/modules/actions/file.py	Thu Dec 08 03:40:55 2016 +0530
@@ -415,7 +415,7 @@
                                         else:
                                                 get_sha256 = False
                                                 get_sha1 = True
-                                        elfhash = elf.get_dynamic(path,
+                                        elfhash = elf.get_hashes(path,
                                             sha1=get_sha1,
                                             sha256=get_sha256)[ehash_attr]
                                 except RuntimeError, e:
--- a/src/modules/elf.c	Thu Dec 08 03:40:53 2016 +0530
+++ b/src/modules/elf.c	Thu Dec 08 03:40:55 2016 +0530
@@ -20,7 +20,7 @@
  */
 
 /*
- *  Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ *  Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <sys/stat.h>
@@ -52,7 +52,7 @@
     int fd;
     int sha1;
     int sha256;
-} dargs_t;
+} hargs_t;
 
 static int
 pythonify_ver_liblist_cb(libnode_t *n, void *info, void *info2)
@@ -130,40 +130,41 @@
 	return (fd);
 }
 
-static dargs_t
-py_get_dyn_args(PyObject *args, PyObject *kwargs)
+static hargs_t
+py_get_hash_args(PyObject *args, PyObject *kwargs)
 {
 	int fd = -1;
 	char *f;
         int get_sha1 = 1;
         int get_sha256 = 0;
 
-        dargs_t dargs;
-        dargs.fd = -1;
+        hargs_t hargs;
+        hargs.fd = -1;
+
         /*
          * By default, we always get an SHA-1 hash, and never get an SHA-2
          * hash.
          */
-        dargs.sha1 = 1;
-        dargs.sha256 = 0;
+        hargs.sha1 = 1;
+        hargs.sha256 = 0;
 
         static char *kwlist[] = {"fd", "sha1", "sha256", NULL};
 
 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ii", kwlist, &f,
             &get_sha1, &get_sha256)) {
 		PyErr_SetString(PyExc_ValueError, "could not parse argument");
-		return (dargs);
+		return (hargs);
 	}
 
 	if ((fd = open(f, O_RDONLY)) < 0) {
 		PyErr_SetFromErrnoWithFilename(PyExc_OSError, f);
-		return (dargs);
+		return (hargs);
 	}
 
-        dargs.fd = fd;
-        dargs.sha1 = get_sha1;
-        dargs.sha256 = get_sha256;
-	return (dargs);
+        hargs.fd = fd;
+        hargs.sha1 = get_sha1;
+        hargs.sha256 = get_sha256;
+	return (hargs);
 }
 
 /*
@@ -236,11 +237,81 @@
 }
 
 /*
- * Returns a dictionary with the relevant information.  No longer
- * accurately titled "get_dynamic," as can return hashes as well.
+ * Returns a dictionary with the requested hash(es).
+ *
+ * Dictionary format:
+ *
+ * {
+ *	elfhash: "sha1hash",
+ *	pkg.content-type.sha256: "sha2hash"
+ * }
+ *
+ * If a hash was not requested, it is omitted from the dictionary.
  *
- * The hash is currently of the following sections (when present):
- * 		.text .data .data1 .rodata .rodata1
+ */
+/*ARGSUSED*/
+static PyObject *
+get_hashes(PyObject *self, PyObject *args, PyObject *keywords)
+{
+	hargs_t		hargs;
+	hashinfo_t	*h = NULL;
+	PyObject	*pdict = NULL;
+	char            hexchars[17] = "0123456789abcdef";
+
+	hargs = py_get_hash_args(args, keywords);
+	if (hargs.fd < 0)
+		return (NULL);
+
+	if ((h = gethashes(hargs.fd, hargs.sha1, hargs.sha256)) == NULL)
+		goto out;
+
+	if ((pdict = PyDict_New()) == NULL)
+		goto out;
+
+	if (hargs.sha1 > 0) {
+		int	i;
+		char	hexhash[41];
+
+		for (i = 0; i < 20; i++) {
+			hexhash[2 * i] = hexchars[(h->hash[i] & 0xf0) >> 4];
+			hexhash[2 * i + 1] = hexchars[h->hash[i] & 0x0f];
+		}
+		hexhash[40] = '\0';
+		if (PyDict_SetItemString(pdict, "elfhash",
+			Py_BuildValue("s", hexhash)) != 0)
+			goto pyerror;
+	}
+
+	if (hargs.sha256 > 0) {
+		int	i;
+		char	hexhash[65];
+
+		for (i = 0; i < 32; i++) {
+			hexhash[2 * i] = hexchars[(h->hash256[i] & 0xf0) >> 4];
+			hexhash[2 * i + 1] = hexchars[h->hash256[i] & 0x0f];
+		}
+		hexhash[64] = '\0';
+		if (PyDict_SetItemString(pdict, "pkg.content-type.sha256",
+			Py_BuildValue("s", hexhash)) != 0)
+			goto pyerror;
+	}
+
+	goto out;
+
+pyerror:
+	Py_CLEAR(pdict);
+
+out:
+	(void) close(hargs.fd);
+
+	if (h != NULL)
+		free(h);
+
+	return (pdict);
+}
+
+/*
+ * Returns a dictionary with the relevant information.
  *
  * Dictionary format:
  *
@@ -248,17 +319,11 @@
  *	runpath: "/path:/entries",
  *	defs: ["version", ... ],
  *	deps: [["file", ["versionlist"]], ...],
- * 	elfhash: "sha1hash"
- *      pkg.elf.sha256: "sha2hash"
  * }
  *
  * If any item is empty or has no value, it is omitted from the
  * dictionary.
  *
- * The keyword arguments "sha1" and "sha256" are allowed, which
- * take Python booleans, declaring which hashes should be
- * computed on the input file.
- *
  * XXX: Currently, defs contains some duplicate entries.  There
  * may be meaning attached to this, or it may just be something
  * worth trimming out at this stage or above.
@@ -266,47 +331,52 @@
  */
 /*ARGSUSED*/
 static PyObject *
-get_dynamic(PyObject *self, PyObject *args, PyObject *keywords)
+get_dynamic(PyObject *self, PyObject *args)
 {
-	int 	i;
-        dargs_t         dargs;
+	int	 	i;
+        int		fd;
 	dyninfo_t 	*dyn = NULL;
 	PyObject	*pdep = NULL;
 	PyObject	*pdef = NULL;
 	PyObject	*pdict = NULL;
-	char		hexhash[41];
-        char            hexsha256[65];
-	char		hexchars[17] = "0123456789abcdef";
 
-	dargs = py_get_dyn_args(args, keywords);
-        if (dargs.fd < 0)
+	fd = py_get_fd(args);
+        if (fd < 0)
 		return (NULL);
 
-	if ((dyn = getdynamic(dargs.fd, dargs.sha1, dargs.sha256)) == NULL)
+	if ((dyn = getdynamic(fd)) == NULL)
 		goto out;
 
-	pdict = PyDict_New();
+	if ((pdict = PyDict_New()) == NULL)
+		goto out;
+
 	if (dyn->deps->head) {
-		pdep = PyList_New(0);
+		if ((pdep = PyList_New(0)) == NULL)
+			goto err;
 		if (liblist_foreach(
 		    dyn->deps, pythonify_2dliblist_cb, pdep, dyn) == -1)
 			goto err;
-		PyDict_SetItemString(pdict, "deps", pdep);
+		if (PyDict_SetItemString(pdict, "deps", pdep) != 0)
+			goto err;
 	}
 	if (dyn->def) {
 		char *str;
 
-		pdef = PyList_New(0);
+		if ((pdef = PyList_New(0)) == NULL)
+			goto err;
 		if (liblist_foreach(
 		    dyn->vers, pythonify_1dliblist_cb, pdef, dyn) == -1)
 			goto err;
-		PyDict_SetItemString(pdict, "vers", pdef);
+		if (PyDict_SetItemString(pdict, "vers", pdef) != 0)
+			goto err;
 		if ((str = elf_strptr(
 		    dyn->elf, dyn->dynstr, dyn->def)) == NULL) {
 			PyErr_SetString(ElfError, elf_errmsg(-1));
 			goto err;
 		}
-		PyDict_SetItemString(pdict, "def", Py_BuildValue("s", str));
+		if (PyDict_SetItemString(pdict, "def",
+			Py_BuildValue("s", str)) != 0)
+			goto err;
 	}
 	if (dyn->runpath) {
 		char *str;
@@ -316,49 +386,30 @@
 			PyErr_SetString(ElfError, elf_errmsg(-1));
 			goto err;
 		}
-		PyDict_SetItemString(pdict, "runpath", Py_BuildValue("s", str));
+		if (PyDict_SetItemString(pdict, "runpath",
+			Py_BuildValue("s", str)) != 0)
+			goto err;
 	}
 
-        if (dargs.sha1 > 0) {
-                for (i = 0; i < 20; i++) {
-                        hexhash[2 * i] = hexchars[(dyn->hash[i] & 0xf0) >> 4];
-                        hexhash[2 * i + 1] = hexchars[dyn->hash[i] & 0x0f];
-                }
-                hexhash[40] = '\0';
-        	PyDict_SetItemString(pdict, "elfhash",
-                    Py_BuildValue("s", hexhash));
-        }
-
-        if (dargs.sha256 > 0) {
-                for (i = 0; i < 32; i++) {
-                        hexsha256[2 * i] = \
-                            hexchars[(dyn->hash256[i] & 0xf0) >> 4];
-                        hexsha256[2 * i + 1] = hexchars[dyn->hash256[i] & 0x0f];
-                }
-                hexsha256[64] = '\0';
-                PyDict_SetItemString(pdict, "pkg.content-type.sha256",
-                    Py_BuildValue("s", hexsha256));
-        }
 	goto out;
 
 err:
-	PyDict_Clear(pdict);
-	Py_DECREF(pdict);
-	pdict = NULL;
+	Py_CLEAR(pdict);
 
 out:
 	if (dyn != NULL)
             dyninfo_free(dyn);
 
-	(void) close(dargs.fd);
+	(void) close(fd);
 	return (pdict);
 }
 
 static PyMethodDef methods[] = {
 	{ "is_elf_object", elf_is_elf_object, METH_VARARGS },
 	{ "get_info", get_info, METH_VARARGS },
-	{ "get_dynamic", (PyCFunction)get_dynamic,
-        METH_VARARGS | METH_KEYWORDS},
+	{ "get_dynamic", (PyCFunction)get_dynamic, METH_VARARGS },
+	{ "get_hashes", (PyCFunction)get_hashes, 
+	  METH_VARARGS | METH_KEYWORDS },
 	{ NULL, NULL }
 };
 
--- a/src/modules/elfextract.c	Thu Dec 08 03:40:53 2016 +0530
+++ b/src/modules/elfextract.c	Thu Dec 08 03:40:55 2016 +0530
@@ -20,12 +20,13 @@
  */
 
 /*
- *  Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ *  Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <libelf.h>
 #include <gelf.h>
 
+#include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/uio.h>
@@ -255,75 +256,32 @@
 	return (hi);
 }
 
-/*
- * For ELF nontriviality: Need to turn an ELF object into a unique hash.
- *
- * From Eric Saxe's investigations, we see that the following sections can
- * generally be ignored:
- *
- *    .SUNW_signature, .comment, .SUNW_dof, .debug, .plt, .rela.bss,
- *    .rela.plt, .line, .note
- *
- * Conversely, the following sections are generally significant:
- *
- *    .rodata.str1.8, .rodata.str1.1, .rodata, .data1, .data, .text
- *
- * Accordingly, we will hash on the latter group of sections to determine our
- * ELF hash.
- */
-static int
-hashsection(char *name)
-{
-	if (strcmp(name, ".SUNW_signature") == 0 ||
-	    strcmp(name, ".comment") == 0 ||
-	    strcmp(name, ".SUNW_dof") == 0 ||
-	    strcmp(name, ".debug") == 0 ||
-	    strcmp(name, ".plt") == 0 ||
-	    strcmp(name, ".rela.bss") == 0 ||
-	    strcmp(name, ".rela.plt") == 0 ||
-	    strcmp(name, ".line") == 0 ||
-	    strcmp(name, ".note") == 0 ||
-	    strcmp(name, ".compcom") == 0)
-		return (0);
-
-	return (1);
-}
+typedef struct hashcb_data {
+	char		*base;
+	SHA1_CTX	*s1c;
+	SHA256_CTX	*s2c;
+} hashcb_data_t;
 
 /*
- * Reads a section in 64k increments, adding it to the hash.
+ * Hashes a range from an mmap'd elf file
  */
-static int
-readhash(int fd, SHA1_CTX *shc, SHA256_CTX *shc2, off_t offset, off_t size,
-    int sha1, int sha256)
+static void
+elfhash_cb(size_t offset, size_t size, void *udata)
 {
-	off_t n;
-	char hashbuf[64 * 1024];
-	ssize_t rbytes;
+	hashcb_data_t *h = (hashcb_data_t *)udata;
 
 	if (!size)
-		return (0);
+		return;
 
-	if (lseek(fd, offset, SEEK_SET) == -1) {
-		PyErr_SetFromErrno(PyExc_IOError);
-		return (-1);
+	if (h->s1c != NULL) {
+		SHA1Update(h->s1c, h->base + offset, size);
 	}
 
-	do {
-		n = MIN(size, sizeof (hashbuf));
-		if ((rbytes = read(fd, hashbuf, n)) == -1) {
-			PyErr_SetFromErrno(PyExc_IOError);
-			return (-1);
-		}
-                if (sha1 > 0) {
-		        SHA1Update(shc, hashbuf, rbytes);
-                }
-                if (sha256 > 0) {
-                        SHA256Update(shc2, hashbuf, rbytes);
-                }
-		size -= rbytes;
-	} while (size != 0);
+	if (h->s2c != NULL) {
+		SHA256Update(h->s2c, h->base + offset, size);
+	}
 
-	return (0);
+	return;
 }
 
 /*
@@ -331,11 +289,9 @@
  * information we want from an ELF file.  Returns NULL
  * if it can't find everything (eg. not ELF file, wrong
  * class of ELF file).
- * If sha1 is > 0, we produce an SHA1 hash as part of the returned dictionary.
- * If sha256 is > 0, we include an SHA2 256 hash in the returned dictionary.
  */
 dyninfo_t *
-getdynamic(int fd, int sha1, int sha256)
+getdynamic(int fd)
 {
 	Elf		*elf = NULL;
 	Elf_Scn		*scn = NULL;
@@ -383,12 +339,6 @@
 	}
 
 	/* get useful sections */
-        if (sha1 > 0) {
-                SHA1Init(&shc);
-        }
-        if (sha256 > 0) {
-                SHA256Init(&shc2);
-        }
 	while ((scn = elf_nextscn(elf, scn))) {
 		if (gelf_getshdr(scn, &shdr) != &shdr) {
 			PyErr_SetString(ElfError, elf_errmsg(-1));
@@ -400,36 +350,6 @@
 			goto bad;
 		}
 
-		if (hashsection(name) && (sha1 > 0 || sha256 > 0)) {
-			if (shdr.sh_type == SHT_NOBITS) {
-				/*
-				 * We can't just push shdr.sh_size into
-				 * SHA1Update(), as its raw bytes will be
-				 * different on x86 than they are on sparc.
-				 * Convert to network byte-order first.
-				 */
-				uint64_t n = shdr.sh_size;
-				uint64_t mask = 0xffffffff00000000ULL;
-				uint32_t top = htonl((uint32_t)((n & mask) >> 32));
-				uint32_t bot = htonl((uint32_t)n);
-                                if (sha1 > 0) {
-				        SHA1Update(&shc, &top, sizeof (top));
-                                        SHA1Update(&shc, &bot, sizeof (bot));
-                                }
-                                if (sha256 > 0) {
-                                        SHA256Update(&shc2, &top, sizeof (top));
-                                        SHA256Update(&shc2, &bot, sizeof (bot));
-                                }
-			} else {
-				int hash;
-                                hash = readhash(fd, &shc, &shc2, shdr.sh_offset,
-				    shdr.sh_size, sha1, sha256);
-
-				if (hash == -1)
-					goto bad;
-			}
-		}
-
 		switch (shdr.sh_type) {
 		case SHT_DYNAMIC:
 			if (!(data_dyn = elf_getdata(scn, NULL))) {
@@ -604,12 +524,6 @@
 	dyn->deps = deps;
 	dyn->def = def;
 	dyn->vers = verdef;
-        if (sha1 > 0) {
-	        SHA1Final(dyn->hash, &shc);
-        }
-        if (sha256 > 0) {
-                SHA256Final(dyn->hash256, &shc2);
-        }
 	return (dyn);
 
 bad:
@@ -632,3 +546,80 @@
 	(void) elf_end(dyn->elf);
 	free(dyn);
 }
+
+/*
+ * gethashes - returns a struct filled with the hashes computed from an ELF
+ * file.  Returns NULL if it encounters a problem (eg. not ELF file, offset out
+ * of range).
+ */
+hashinfo_t *
+gethashes(int fd, int dosha1, int dosha2)
+{
+	hashinfo_t	*hashes = NULL;
+	hashcb_data_t	hdata = { NULL, NULL, NULL };
+	Elf		*elf;
+	struct stat	status;
+
+	if ((elf_version(EV_CURRENT) == EV_NONE) ||
+	    ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)) {
+		PyErr_SetString(ElfError, elf_errmsg(-1));
+		return (NULL);
+	}
+
+	if ((fstat(fd, &status) == -1) ||
+	    ((hdata.base = mmap(NULL, status.st_size, PROT_READ, MAP_PRIVATE,
+	    fd, 0)) == MAP_FAILED)) {
+		PyErr_SetString(ElfError, strerror(errno));
+		goto hash_out;
+	}
+	    
+	if (dosha1 > 0) {
+		hdata.s1c = (SHA1_CTX *)malloc(sizeof (SHA1_CTX));
+		if (hdata.s1c == NULL) {
+			(void) PyErr_NoMemory();
+		        goto hash_out;
+		}
+		SHA1Init(hdata.s1c);
+	}
+
+	if (dosha2 > 0) {
+		hdata.s2c = (SHA256_CTX *)malloc(sizeof (SHA256_CTX));
+		if (hdata.s2c == NULL) {
+			(void) PyErr_NoMemory();
+			goto hash_out;
+		}
+		SHA256Init(hdata.s2c);
+	}
+
+	if (!gelf_sign_range(elf, elfhash_cb, ELF_SR_INTERPRET, &hdata)) {
+		PyErr_SetString(ElfError, elf_errmsg(-1));
+		goto hash_out;
+	}
+
+	if ((hashes = malloc(sizeof (hashinfo_t))) == NULL) {
+		(void) PyErr_NoMemory();
+		goto hash_out;
+	}
+
+	if (dosha1 > 0) {
+		SHA1Final(hashes->hash, hdata.s1c);
+	}
+
+	if (dosha2 > 0) {
+		SHA256Final(hashes->hash256, hdata.s2c);
+	}
+
+hash_out:
+	(void) elf_end(elf);
+
+	if (hdata.base)
+		munmap(hdata.base, status.st_size);
+
+	if (hdata.s1c)
+		free(hdata.s1c);
+
+	if (hdata.s2c)
+		free(hdata.s2c);
+
+	return (hashes);
+}
--- a/src/modules/elfextract.h	Thu Dec 08 03:40:53 2016 +0530
+++ b/src/modules/elfextract.h	Thu Dec 08 03:40:55 2016 +0530
@@ -20,7 +20,7 @@
  */
 
 /*
- *  Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ *  Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef _ELFEXTRACT_H
@@ -46,11 +46,13 @@
 					/* 	offsets)		   */
 	liblist_t 	*vers;		/* version provided list (also	   */
 					/* 	contains offsets)	   */
+	Elf		*elf;		/* elf data -- must be freed	   */
+} dyninfo_t;
+
+typedef struct hashinfo {
 	unsigned char	hash[20];	/* SHA1 Hash of significant segs.  */
      	unsigned char	hash256[32];	/* SHA2 Hash of significant segs.  */
-
-	Elf		*elf;		/* elf data -- must be freed	   */
-} dyninfo_t;
+} hashinfo_t;
 
 typedef struct hdrinfo {
 	int type;			/* e_type		*/
@@ -62,7 +64,8 @@
 
 extern int iself(int fd);
 extern int iself32(int fd);
-extern dyninfo_t *getdynamic(int fd, int sha1, int sha256);
+extern dyninfo_t *getdynamic(int fd);
+extern hashinfo_t *gethashes(int fd, int sha1, int sha256);
 extern void dyninfo_free(dyninfo_t *dyn);
 extern hdrinfo_t *getheaderinfo(int fd);
 
--- a/src/modules/flavor/elf.py	Thu Dec 08 03:40:53 2016 +0530
+++ b/src/modules/flavor/elf.py	Thu Dec 08 03:40:55 2016 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
 #
 
 import os
@@ -176,7 +176,7 @@
 
         try:
                 ei = elf.get_info(proto_file)
-                ed = elf.get_dynamic(proto_file, sha1=False, sha256=False)
+                ed = elf.get_dynamic(proto_file)
         except elf.ElfError, e:
                 raise BadElfFile(proto_file, e)
         deps = [
--- a/src/modules/server/transaction.py	Thu Dec 08 03:40:53 2016 +0530
+++ b/src/modules/server/transaction.py	Thu Dec 08 03:40:55 2016 +0530
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
 #
 
 import calendar
@@ -517,16 +517,15 @@
                                         else:
                                                 get_sha1 = False
 
-                                        dyn = elf.get_dynamic(
-                                            elf_name, sha1=get_sha1,
-                                            sha256=get_sha256)
+                                        hashes = elf.get_hashes(elf_name,
+                                            sha1=get_sha1, sha256=get_sha256)
 
                                         if get_sha1:
-                                                action.attrs[elf1] = dyn[elf1]
+                                                action.attrs[elf1] = hashes[elf1]
 
                                         if get_sha256:
                                                 action.attrs[elf256] = \
-                                                    dyn[elf256]
+                                                    hashes[elf256]
 
                                 except elf.ElfError:
                                         pass
--- a/src/tests/api/t_elf.py	Thu Dec 08 03:40:53 2016 +0530
+++ b/src/tests/api/t_elf.py	Thu Dec 08 03:40:55 2016 +0530
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 
-# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
 
 import testutils
 if __name__ == "__main__":
@@ -41,7 +41,6 @@
         elf_paths = [
             "/usr/bin/mdb",
             "/usr/bin/__ARCH__/mdb",
-            "/dev/ksyms",
             "/usr/lib/libc.so",
             "/usr/lib/__ARCH__/libc.so",
             "/usr/lib/crti.o",
@@ -59,6 +58,7 @@
                 os.chdir(self.test_root)
                 self.assertEqual(elf.is_elf_object(p), False)
                 self.assertRaises(elf.ElfError, elf.get_dynamic, p)
+                self.assertRaises(elf.ElfError, elf.get_hashes, p)
                 self.assertRaises(elf.ElfError, elf.get_info, p)
 
         def test_non_existent(self):
@@ -68,6 +68,7 @@
                 p = "does/not/exist"
                 self.assertRaises(OSError, elf.is_elf_object, p)
                 self.assertRaises(OSError, elf.get_dynamic, p)
+                self.assertRaises(OSError, elf.get_hashes, p)
                 self.assertRaises(OSError, elf.get_info, p)
 
         def test_valid_elf(self):
@@ -79,10 +80,11 @@
                         self.assert_(os.path.exists(p), "%s does not exist" % p)
                         self.assertEqual(elf.is_elf_object(p), True)
                         elf.get_dynamic(p)
+                        elf.get_hashes(p)
                         elf.get_info(p)
 
-        def test_get_dynamic_params(self):
-                """Test that get_dynamic(..) returns checksums according to the
+        def test_get_hashes_params(self):
+                """Test that get_hashes(..) returns checksums according to the
                 parameters passed to the method."""
 
                 # Check that the hashes generated have the correct length
@@ -91,19 +93,19 @@
                 sha256_len = 64
 
                 # the default is to return an SHA-1 elfhash only
-                d = elf.get_dynamic(self.elf_paths[0])
+                d = elf.get_hashes(self.elf_paths[0])
                 self.assert_(len(d["elfhash"]) == sha1_len)
                 self.assert_("pkg.content-type.sha256" not in d)
 
-                d = elf.get_dynamic(self.elf_paths[0], sha256=True)
+                d = elf.get_hashes(self.elf_paths[0], sha256=True)
                 self.assert_(len(d["elfhash"]) == sha1_len)
                 self.assert_(len(d["pkg.content-type.sha256"]) == sha256_len)
 
-                d = elf.get_dynamic(self.elf_paths[0], sha1=False, sha256=True)
+                d = elf.get_hashes(self.elf_paths[0], sha1=False, sha256=True)
                 self.assert_("elfhash" not in d)
                 self.assert_(len(d["pkg.content-type.sha256"]) == sha256_len)
 
-                d = elf.get_dynamic(self.elf_paths[0], sha1=False, sha256=False)
+                d = elf.get_hashes(self.elf_paths[0], sha1=False, sha256=False)
                 self.assert_("elfhash" not in d)
                 self.assert_("pkg.content-type.sha256" not in d)